From: Rudolf Polzer <[email protected]>
If more input is read from the engine than there is space in
`engineinputbuf`, these overflows could happen due to use of unlimited
`strcat` and a mistake in use of `strlen` to terminate the string:
- engine provided >= `BUF_SIZE` bytes: `strcat` call would read arbitrarily
beyond `engineinputaux` and write beyond `engineinputbuf`. Then, a NUL
byte will be written `BUF_SIZE` behind the engine input buffer,
usually pointing into arbitrary RAM. In my build, this would clear the
beginning of `answerFromEngineExpected`, which _potentially_ (didn't
happen yet) could cause an endless loop; however order of static
globals is not guaranteed and may depend on compiler. It would also
write nonsense into `zerochar` which could break other calls in funny
ways.
- Engine provided less than `BUF_SIZE` bytes, but more than fit into
`engineinputbuf`: then `strcat` will overflow into whatever follows
`engineinputbuf` (in my build, `zerochar`). Also, a zero write is
written beyond that too, but still into `zerochar`.
- Engine provided more than `BUF_SIZE / 2` bytes: then the final NUL
byte is still written somehwere beyond `engineinputbuf`, in my build
into `zerochar` which admittedly is harmless.
The fix is to redo the buffer management in a working way.
---
src/frontend/engine.cc | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/frontend/engine.cc b/src/frontend/engine.cc
index b79ed67..f39814e 100644
--- a/src/frontend/engine.cc
+++ b/src/frontend/engine.cc
@@ -148,11 +148,16 @@ int ReadFromEngine( void )
printf( "Error reading engine input.\n" );
} else if ( engineinputready > 0 ) {
/* There are some data from the engine. Store it in buffer */
- strncpy( engineinputaux, zerochar, BUF_SIZE );
nread = read( pipefd_a2f[0], engineinputaux, BUF_SIZE );
+ int prev_len = strlen(engineinputbuf);
+ int nremaining = sizeof(engineinputbuf) - prev_len - 1;
+ if (nread > nremaining) {
+ printf( "Overflow reading engine input. Some input has been cut off.\n"
);
+ nread = nremaining;
+ }
/*write( STDOUT_FILENO, engineinputaux, BUF_SIZE );*/
- strcat( engineinputbuf, engineinputaux );
- engineinputbuf[strlen( engineinputbuf ) + nread] = '\0';
+ memcpy(engineinputbuf + prev_len, engineinputaux, nread);
+ engineinputbuf[prev_len + nread] = '\0';
}
return ( engineinputready );
--
2.39.5