From: Rudolf Polzer <divver...@gmail.com>

If more than `BUF_SIZE-2` bytes are read from the user, appending a
newline and a zero byte overflows `userinputaux`, likely running into
`userinputready` which _looks_ at least harmless, but is still undefined
behavior. However, an assert exists to detect that and crash the engine:

```
$ perl -e 'syswrite STDOUT, "e4\n" x 5000' | src/gnuchess --uci
GNU Chess
gnuchess: engine.cc:520: void ForwardUserInputToEngine(): Assertion `nread+1 < 
BUF_SIZE-1' failed.
zsh: done             perl -e 'syswrite STDOUT, "e4\n" x 5000' |
zsh: IOT instruction  src/gnuchess --uci
```

This change fixes the crash by reading the correct amount of bytes.
---
 src/frontend/engine.cc | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/src/frontend/engine.cc b/src/frontend/engine.cc
index 85e15fb..e8fb3a2 100644
--- a/src/frontend/engine.cc
+++ b/src/frontend/engine.cc
@@ -514,15 +514,18 @@ void ForwardUserInputToEngine( void )
     printf( "Error reading user input.\n" );
   } else if ( userinputready > 0 ) {
     /* There are some data from the user. Read the data */
-    strncpy( userinputaux, zerochar, BUF_SIZE );
-    nread = read( STDIN_FILENO, userinputaux, BUF_SIZE );
-    /* Send the data to the engine */
-    assert( nread+1 < BUF_SIZE-1 );
-    if ( strcmp(userinputaux,"quit") == 0 || strcmp(userinputaux,"quit\n") == 
0 ) {
-         SET (flags, QUIT);
+    nread = read( STDIN_FILENO, userinputaux, BUF_SIZE-2 );
+    if ( nread == -1 ) {
+      printf( "Error reading message from user.\n" );
+      return;
     }
+    /* Send the data to the engine */
+    assert( nread <= BUF_SIZE-2 );
     userinputaux[nread] = '\n';
     userinputaux[nread+1] = '\0';
+    if ( strcmp(userinputaux,"quit\n") == 0 || strcmp(userinputaux,"quit\n\n") 
== 0 ) {
+         SET (flags, QUIT);
+    }
     int outError=0;
     int msg_count=0;
     msg_count = write( pipefd_a2e[1], userinputaux, nread+1 );
-- 
2.39.5


Reply via email to