I just fixed a bug which allowed people to cheat in worm(6). This bug was
found out by deraadt@ when peer reviewing the mail thread in tech@
'Fwd: worm.c removing unused variables'.

To reproduce the bug simply hold spacebar and your worm won't move.

Highlights:
 * Use the unused time variables to record how long has been since the
   last valid key press;
 * Changed the process() function to return whether the key pressed was
   valid or not;
 * Use clock_gettime(CLOCK_UPTIME) instead of gettimeofday() to provide
   reliable clock source even on suspend/wake up;

ok?

Index: worm.c
===================================================================
RCS file: /cvs/src/games/worm/worm.c,v
retrieving revision 1.30
diff -u -p -r1.30 worm.c
--- worm.c      22 Aug 2015 14:47:41 -0000      1.30
+++ worm.c      23 Aug 2015 20:42:42 -0000
@@ -78,7 +78,7 @@ void  leave(int);
 void   life(void);
 void   newpos(struct body *);
 struct body    *newlink(void);
-void   process(int);
+int    process(int);
 void   prize(void);
 int    rnd(int);
 void   setup(void);
@@ -88,10 +88,11 @@ int
 main(int argc, char **argv)
 {
        int retval;
-       struct timeval t, tod;
-       struct timezone tz;
        struct pollfd pfd[1];
        const char *errstr;
+       struct timespec t, tn, tdiff;
+
+       memset(&t, 0, sizeof(t));
 
        setbuf(stdout, outbuf);
        signal(SIGINT, leave);
@@ -154,18 +155,34 @@ main(int argc, char **argv)
                        running--;
                        process(lastch);
                } else {
-                       /* fflush(stdout); */
-                       /* Delay could be a command line option */
-                       t.tv_sec = 1;
-                       t.tv_usec = 0;
-                       (void)gettimeofday(&tod, &tz);
+                       /* Check for user input timeout. */
+                       clock_gettime(CLOCK_UPTIME, &tn);
+                       if (timespeccmp(&t, &tn, <=)) {
+                               t = tn;
+                               t.tv_sec += 1;
+
+                               process(lastch);
+                               continue;
+                       }
+
+                       /* Prepare next read */
                        pfd[0].fd = STDIN_FILENO;
                        pfd[0].events = POLLIN;
-                       retval = poll(pfd, 1, t.tv_sec * 1000 + t.tv_usec / 
1000);
-                       if (retval > 0)
-                               process(getch());
-                       else
-                               process(lastch);
+                       timespecsub(&t, &tn, &tdiff);
+                       retval = poll(pfd, 1, (tdiff.tv_sec * 1000) +
+                           (tdiff.tv_nsec / 1000000));
+
+                       /* Nothing to do if timed out or signal. */
+                       if (retval <= 0)
+                               continue;
+
+                       /* Only update timer if valid key was pressed. */
+                       if (process(getch()) == 0)
+                               continue;
+
+                       /* Update using clock_gettime(), tn is too old now. */
+                       clock_gettime(CLOCK_UPTIME, &t);
+                       t.tv_sec += 1;
                }
        }
 }
@@ -245,7 +262,7 @@ prize(void)
        wrefresh(tv);
 }
 
-void
+int
 process(int ch)
 {
        int x,y;
@@ -300,21 +317,21 @@ process(int ch)
                break;
        case '\f':
                setup();
-               return;
+               return (0);
        case CNTRL('Z'):
                suspend(0);
-               return;
+               return (0);
        case CNTRL('C'):
                crash();
-               return;
+               return (0);
        case CNTRL('D'):
                crash();
-               return;
+               return (0);
        case ERR:
                leave(0);
-               return;
+               return (0);
        default:
-               return;
+               return (0);
        }
        lastch = ch;
        if (growing == 0) {
@@ -352,6 +369,7 @@ process(int ch)
                wmove(tv, head->y, head->x);
                wrefresh(tv);
        }
+       return (1);
 }
 
 struct body *

Reply via email to