1) Fix longstanding math bug with denominator > 1 (wrong probability).
Test case: random -f some_small_file 10000 (in most cases must be no output) 2) Prevent number of lines > RANDOM_MAX (overflow or nothing may be choosed) with EFBIG err() 3) After line is found, terminate list loop for -U case too, since nothing to do in the rest of the loop left.
This commit is contained in:
parent
67cc8dbb1a
commit
2c38883d2a
@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -94,10 +95,11 @@ int
|
||||
randomize_fd(int fd, int type, int unique, double denom)
|
||||
{
|
||||
u_char *buf;
|
||||
u_int numnode, j, selected, slen;
|
||||
u_int slen;
|
||||
u_long i, j, numnode, selected;
|
||||
struct rand_node *n, *prev;
|
||||
int bufleft, eof, fndstr, ret;
|
||||
size_t bufc, buflen, i;
|
||||
size_t bufc, buflen;
|
||||
ssize_t len;
|
||||
|
||||
rand_root = rand_tail = NULL;
|
||||
@ -173,6 +175,11 @@ randomize_fd(int fd, int type, int unique, double denom)
|
||||
(type == RANDOM_TYPE_WORDS && isspace(buf[i])) ||
|
||||
(eof && i == buflen - 1)) {
|
||||
make_token:
|
||||
if (numnode == RANDOM_MAX) {
|
||||
errno = EFBIG;
|
||||
err(1, "too many lines");
|
||||
}
|
||||
numnode++;
|
||||
n = rand_node_allocate();
|
||||
if (-1 != (int)i) {
|
||||
slen = i - (u_long)bufc;
|
||||
@ -188,7 +195,6 @@ randomize_fd(int fd, int type, int unique, double denom)
|
||||
}
|
||||
rand_node_append(n);
|
||||
fndstr = 1;
|
||||
numnode++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -202,16 +208,18 @@ randomize_fd(int fd, int type, int unique, double denom)
|
||||
}
|
||||
|
||||
for (i = numnode; i > 0; i--) {
|
||||
selected = ((int)denom * random())/(RANDOM_MAX / numnode);
|
||||
selected = random() % numnode;
|
||||
|
||||
for (j = 0, prev = n = rand_root; n != NULL; j++, prev = n, n = n->next) {
|
||||
if (j == selected) {
|
||||
if (n->cp == NULL)
|
||||
break;
|
||||
|
||||
ret = printf("%.*s", (int)n->len - 1, n->cp);
|
||||
if (ret < 0)
|
||||
err(1, "printf");
|
||||
if ((int)(denom * random() / RANDOM_MAX) == 0) {
|
||||
ret = printf("%.*s", (int)n->len - 1, n->cp);
|
||||
if (ret < 0)
|
||||
err(1, "printf");
|
||||
}
|
||||
if (unique) {
|
||||
if (n == rand_root)
|
||||
rand_root = n->next;
|
||||
@ -221,8 +229,8 @@ randomize_fd(int fd, int type, int unique, double denom)
|
||||
prev->next = n->next;
|
||||
rand_node_free(n);
|
||||
numnode--;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user