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");