[PROPOSED] zic now checks for signals more often
* NEWS: Mention this. * zic.c (verror, make_links, main, get_rand_u64) (random_dirent, open_outfile, dolink, inputline, infile): Be better about checking for signals, e.g., when the input or the random number generator is giving is trouble, so that it’s easier for the user to control-C out. Although the result is not perfect it should be good enough for practical use. --- NEWS | 2 ++ zic.c | 35 ++++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/NEWS b/NEWS index d4ba011b..fa791cb9 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,8 @@ Unreleased, experimental changes which can occur with adversarial input. (Thanks to GitHub user rootvector2.) + zic now checks for signals more often. + Release 2026a - 2026-03-01 22:59:49 -0800 diff --git a/zic.c b/zic.c index 77396228..c0891001 100644 --- a/zic.c +++ b/zic.c @@ -253,6 +253,7 @@ symlink(char const *target, char const *linkname) (errno = ENOTSUP, -1) #endif +static void check_for_signal(void); static void addtt(zic_t starttime, int type); static int addtype(zic_t, char const *, bool, bool, bool); static void leapadd(zic_t, int, int); @@ -704,6 +705,7 @@ eat(int fnum, lineno num) ATTRIBUTE_FORMAT((printf, 1, 0)) static void verror(const char *const string, va_list args) { + check_for_signal(); /* ** Match the format of "cc" to allow sh users to ** zic ... 2>&1 | error -t "*" -v @@ -1074,6 +1076,7 @@ make_links(void) warning(_("link %s targeting link %s"), links[i].l_linkname, links[i].l_target); } + check_for_signal(); } } @@ -1391,6 +1394,7 @@ main(int argc, char **argv) for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j) continue; outzone(&zones[i], j - i); + check_for_signal(); } make_links(); if (lcltime != NULL) { @@ -1486,9 +1490,11 @@ get_rand_u64(void) static int nwords; if (!nwords) { ssize_t s; - do + for (;; check_for_signal()) { s = getrandom(entropy_buffer, sizeof entropy_buffer, 0); - while (s < 0 && errno == EINTR); + if (! (s < 0 && errno == EINTR)) + break; + } nwords = s < 0 ? -1 : s / sizeof *entropy_buffer; } @@ -1516,7 +1522,7 @@ get_rand_u64(void) rmod = INT_MAX < UINT_FAST64_MAX ? 0 : UINT_FAST64_MAX / nrand + 1, r = 0, rmax = 0; - do { + for (;; check_for_signal()) { uint_fast64_t rmax1 = rmax; if (rmod) { /* Avoid signed integer overflow on theoretical platforms @@ -1527,7 +1533,9 @@ get_rand_u64(void) rmax1 = nrand * rmax1 + rand_max; r = nrand * r + rand(); rmax = rmax < rmax1 ? rmax1 : UINT_FAST64_MAX; - } while (rmax < UINT_FAST64_MAX); + if (UINT_FAST64_MAX <= rmax) + break; + } return r; } @@ -1574,9 +1582,11 @@ random_dirent(char const **name, char **namealloc) *name = *namealloc = dst; } - do + for (;; check_for_signal()) { r = get_rand_u64(); - while (unfair_min <= r); + if (r < unfair_min) + break; + } for (i = 0; i < suffixlen; i++) { dst[dirlen + prefixlen + i] = alphabet[r % alphabetlen]; @@ -1611,7 +1621,7 @@ open_outfile(char const **outname, char **tempname) if (!*tempname) random_dirent(outname, tempname); - while (true) { + for (;; check_for_signal()) { int oflags = O_WRONLY | O_BINARY | O_CREAT | O_EXCL; int fd = open(*outname, oflags, creat_perms); int err; @@ -1725,8 +1735,6 @@ dolink(char const *target, char const *linkname, bool staysymlink) char const *outname = linkname; int targetissym = -2, linknameissym = -2; - check_for_signal(); - if (strcmp(target, "-") == 0) { if (remove(linkname) == 0 || errno == ENOENT || errno == ENOTDIR) return; @@ -1739,7 +1747,7 @@ dolink(char const *target, char const *linkname, bool staysymlink) } } - while (true) { + for (;; check_for_signal()) { if (linkat(AT_FDCWD, target, AT_FDCWD, outname, AT_SYMLINK_FOLLOW) == 0) { link_errno = 0; @@ -1791,7 +1799,7 @@ dolink(char const *target, char const *linkname, bool staysymlink) int symlink_errno = -1; if (contents) { - while (true) { + for (;; check_for_signal()) { if (symlink(contents, outname) == 0) { symlink_errno = 0; break; @@ -1822,7 +1830,7 @@ dolink(char const *target, char const *linkname, bool staysymlink) exit(EXIT_FAILURE); } tp = open_outfile(&outname, &tempname); - while ((c = getc(fp)) != EOF) + for (; (c = getc(fp)) != EOF; check_for_signal()) putc(c, tp); close_file(tp, directory, linkname, tempname); close_file(fp, directory, target, NULL); @@ -1946,7 +1954,7 @@ static bool inputline(FILE *fp, char *buf, ptrdiff_t bufsize) { ptrdiff_t linelen = 0, ch; - while ((ch = getc(fp)) != '\n') { + for (; (ch = getc(fp)) != '\n'; check_for_signal()) { if (ch < 0) { if (ferror(fp)) { error(_("input error")); @@ -2033,6 +2041,7 @@ infile(int fnum, char const *name) default: unreachable(); } } + check_for_signal(); } close_file(fp, NULL, filename(fnum), NULL); if (wantcont) -- 2.51.0
participants (1)
-
Paul Eggert