Hi,

This patch solves two problems.

First, abort if denom is greater than UINT32_MAX. arc4random_uniform
expects an uint32_t. If floor(denom) is greater than UINT32_MAX then
the cast is undefined behaviour.

Second, use consistent error checking for printing the lines. putchar
sets errno while ferrror tests the internal flags of the stream.

-lucic71

Index: random.c
===================================================================
RCS file: /cvs/src/games/random/random.c,v
retrieving revision 1.20
diff -u -p -r1.20 random.c
--- random.c    7 Mar 2016 12:07:56 -0000       1.20
+++ random.c    1 Aug 2022 19:14:11 -0000
@@ -79,6 +79,8 @@ main(int argc, char *argv[])
                        err(1, "%s", *argv);
                if (denom == 0 || *ep != '\0')
                        errx(1, "denominator is not valid.");
+               if ((uint64_t) denom > 0xFFFFFFFF)
+                       errx(1, "denominator out of bounds.");
                break;
        default:
                usage(); 
@@ -103,16 +105,17 @@ main(int argc, char *argv[])
         */
        selected = arc4random_uniform(denom) == 0;
        while ((ch = getchar()) != EOF) {
-               if (selected)
-                       (void)putchar(ch);
-               if (ch == '\n') {
-                       /* End of that line.  See if we got an error. */
-                       if (ferror(stdout))
-                               err(2, "stdout");
+               int retch;
 
+               if (selected) {
+                       errno = 0;
+                       retch = putchar(ch);
+                       if (retch == EOF && errno)
+                               err(2, "putchar");
+               }
+               if (ch == '\n')
                        /* Now see if the next line is to be printed. */
                        selected = arc4random_uniform(denom) == 0;
-               }
        }
        if (ferror(stdin))
                err(2, "stdin");

Reply via email to