From c3833e1c5410c505f6e937bab37791c407697613 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Fri, 24 Jul 2026 14:54:14 +0900 Subject: [PATCH 1/6] hotfix: rewrite rand_range logic --- hhss/c/prelex.c | 2 +- hhss/c/replace.c | 9 ++++----- lib/utils.c | 36 +++++++++++++++++++++++++++++++++--- yandere/c/noise.c | 4 ++-- 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/hhss/c/prelex.c b/hhss/c/prelex.c index 8618b53..4221ee7 100644 --- a/hhss/c/prelex.c +++ b/hhss/c/prelex.c @@ -10,7 +10,7 @@ extern array_t *prelex(array_t *db, int datcnt) { lastpos = array_size(db); for (int k = 0; k < datcnt; k++) { - rv = rand_range(0, lastpos); /* [0, lp) */ + rv = rand_range(0, lastpos - 1); /* [0, lp - 1] */ curr = array_get(db, rv); last = array_get(db, lastpos - 1); diff --git a/hhss/c/replace.c b/hhss/c/replace.c index cf1aa36..97def0b 100644 --- a/hhss/c/replace.c +++ b/hhss/c/replace.c @@ -27,7 +27,7 @@ extern void replace_templates(array_t *pts, array_t *rtdb) { if (rtslen == 0) synerr_empty(); - v = rand_range(0, rtslen); + v = rand_range(0, rtslen - 1); rt = *((char **) array_get(rts, v)); sectarr = rtdbquery(rtdb, rt); @@ -80,9 +80,8 @@ static void rthandle_user(symbol_t *sym, array_t *sectarr) { goto common; } - do { - r = rand_range(0, siz); - } while (r == pre_user); + do r = rand_range(0, siz - 1); + while (r == pre_user); pre_user = r; common: @@ -93,7 +92,7 @@ static void rthandle_else(symbol_t *sym, array_t *sectarr) { int r, siz; siz = array_size(sectarr); - r = rand_range(0, siz); + r = rand_range(0, siz - 1); rthandle_common(sym, sectarr, r); } diff --git a/lib/utils.c b/lib/utils.c index 7d61798..d6036ca 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -5,10 +5,40 @@ extern void seed(void) { srand(time(NULL)); } +/* Refer to https://c-faq.com/lib/randrange.html */ extern int rand_range(int min, int max) { - if (max <= 0) - VERR("max must be greater than 0, but given %d", max); - return min + rand() / (RAND_MAX / max + 1); + if (min >= max) + ERR("min should be less than max."); + + unsigned long nbucket; /* number of buckets */ + unsigned int bucket_siz, threshold, rv; + + /* since range is long, it's safe if max and min + were INT_MAX and INT_MIN, respectively */ + nbucket = 1UL + max - min; + /* since rand() returns [0,RAND_MAX], the number of total + possible return values is RAND_MAX + 1 */ + /* specify 'u' in order to treat it as a unsigned int value */ + bucket_siz = (RAND_MAX + 1UL) / nbucket; + threshold = bucket_siz * nbucket; + + do rv = rand(); + while (rv >= threshold); + + return min + (int) (rv / bucket_siz); + + /* An example simulation. + Suppose RAND_MAX = 10, nbucket = 3. + Since bucket_siz = (10 + 1) / 3 = 3, + threshold = 3 * 3 = 9. + Since RAND_MAX is 10, rand() returns [0,10]. + If rand returns 9 or 10, re-roll. + If rand returns 0 ~ 8, then + rv = 0,1,2 => rv / 3 = 0 + rv = 3,4,5 => rv / 3 = 1 + rv = 6,7,8 => rv / 3 = 2 + Thus, all numbers (min ~ max) have an equal + possibility to appear. */ } extern int mblen_(char ch) { diff --git a/yandere/c/noise.c b/yandere/c/noise.c index d0e332b..2cb92ef 100644 --- a/yandere/c/noise.c +++ b/yandere/c/noise.c @@ -6,13 +6,13 @@ extern void noise(const char *msg) { bool overflow; for (i = k = 0; msg[i] != '\0'; /* empty */) { - rv = rand_range(0, 6); + rv = rand_range(0, 5); chlen = mblen_(msg[i]); overflow = (k + chlen) >= (BUFMAX - 1); if (overflow) break; if (rv == 0) { /* 1/6 chance */ - buf[k++] = *("#?@" + rand_range(0, 3)); + buf[k++] = *("#?@" + rand_range(0, 2)); i += chlen; } else for (int m = 0; m < chlen; m++) From 09bf3c55ce7cd18f59d0369525168221ca373ca7 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Fri, 24 Jul 2026 17:24:20 +0900 Subject: [PATCH 2/6] hotfix: handle min == max case --- lib/utils.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/utils.c b/lib/utils.c index d6036ca..f601c43 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -7,9 +7,12 @@ extern void seed(void) { /* Refer to https://c-faq.com/lib/randrange.html */ extern int rand_range(int min, int max) { - if (min >= max) + if (min > max) ERR("min should be less than max."); + if (min == max) + return min; + unsigned long nbucket; /* number of buckets */ unsigned int bucket_siz, threshold, rv; From c3553d085f69622f6f9614cbf0b3f780f3f5f4ed Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Sat, 25 Jul 2026 02:07:32 +0900 Subject: [PATCH 3/6] hotfix: check if max - min > RAND_MAX --- lib/utils.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/utils.c b/lib/utils.c index f601c43..bf6bfe0 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -8,21 +8,34 @@ extern void seed(void) { /* Refer to https://c-faq.com/lib/randrange.html */ extern int rand_range(int min, int max) { if (min > max) - ERR("min should be less than max."); + VERR("min must be less than or equal to max," + " but given min=%d, max=%d", min, max); + + /* implicit integer promotion happens */ + /* INT_MAX - INT_MIN == UINT_MAX */ + if ((unsigned int) max - min > RAND_MAX) + VERR("range too large to handle!" + " max - min must <= %d (RAND_MAX)," + " but given min=%d, max=%d", min, max); if (min == max) return min; - unsigned long nbucket; /* number of buckets */ - unsigned int bucket_siz, threshold, rv; + unsigned int + nbucket, /* number of buckets */ + bucket_siz, + threshold, + rv; - /* since range is long, it's safe if max and min - were INT_MAX and INT_MIN, respectively */ - nbucket = 1UL + max - min; + /* like there are 5 numbers in [1,5] since 5 - 1 + 1 = 5, + max - min + 1 means the count of the numbers in [max, min] */ + /* since max - min <= RAND_MAX <= INT_MAX, it's fine to add 1 */ + nbucket = 1U + max - min; /* since rand() returns [0,RAND_MAX], the number of total - possible return values is RAND_MAX + 1 */ - /* specify 'u' in order to treat it as a unsigned int value */ - bucket_siz = (RAND_MAX + 1UL) / nbucket; + possible return values is RAND_MAX - 0 + 1 */ + /* specify 'U' in order to treat it as a unsigned int value */ + /* integer promotion also happens */ + bucket_siz = (RAND_MAX + 1U) / nbucket; threshold = bucket_siz * nbucket; do rv = rand(); @@ -30,9 +43,9 @@ extern int rand_range(int min, int max) { return min + (int) (rv / bucket_siz); - /* An example simulation. + /* EXAMPLE CASE Suppose RAND_MAX = 10, nbucket = 3. - Since bucket_siz = (10 + 1) / 3 = 3, + Since bucket_siz = (10 + 1) / 3 = 3 (fractional part discarded), threshold = 3 * 3 = 9. Since RAND_MAX is 10, rand() returns [0,10]. If rand returns 9 or 10, re-roll. @@ -40,7 +53,7 @@ extern int rand_range(int min, int max) { rv = 0,1,2 => rv / 3 = 0 rv = 3,4,5 => rv / 3 = 1 rv = 6,7,8 => rv / 3 = 2 - Thus, all numbers (min ~ max) have an equal + Thus, all numbers in [min, max] have an equal possibility to appear. */ } From 8a53ef98bc40a2d0d2ecddf2851c8f0f435cf290 Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Sat, 25 Jul 2026 05:19:58 +0900 Subject: [PATCH 4/6] hotfix: fix the comment --- lib/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils.c b/lib/utils.c index bf6bfe0..12f938e 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -28,7 +28,7 @@ extern int rand_range(int min, int max) { rv; /* like there are 5 numbers in [1,5] since 5 - 1 + 1 = 5, - max - min + 1 means the count of the numbers in [max, min] */ + max - min + 1 means the count of the numbers in [min, max] */ /* since max - min <= RAND_MAX <= INT_MAX, it's fine to add 1 */ nbucket = 1U + max - min; /* since rand() returns [0,RAND_MAX], the number of total From a6ebc3e6c8946c26efa55af3a0372c449b7a95ef Mon Sep 17 00:00:00 2001 From: Doohyeon Won Date: Sat, 25 Jul 2026 05:20:48 +0900 Subject: [PATCH 5/6] hotfix: fix the comment --- lib/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils.c b/lib/utils.c index 12f938e..63ee530 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -15,7 +15,7 @@ extern int rand_range(int min, int max) { /* INT_MAX - INT_MIN == UINT_MAX */ if ((unsigned int) max - min > RAND_MAX) VERR("range too large to handle!" - " max - min must <= %d (RAND_MAX)," + " max - min must be <= %d (RAND_MAX)," " but given min=%d, max=%d", min, max); if (min == max) From 20b0bd32c15b29bf25daec3ac86006b98316eb6f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 25 Jul 2026 04:28:28 +0000 Subject: [PATCH 6/6] hotfix: fix missing RAND_MAX argument in VERR format string --- lib/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils.c b/lib/utils.c index 63ee530..1bfd550 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -16,7 +16,7 @@ extern int rand_range(int min, int max) { if ((unsigned int) max - min > RAND_MAX) VERR("range too large to handle!" " max - min must be <= %d (RAND_MAX)," - " but given min=%d, max=%d", min, max); + " but given min=%d, max=%d", RAND_MAX, min, max); if (min == max) return min;