Thank you very much for looking into this and for the fix. I really appreciate your quick analysis and explanation.
4. 1. 2026 2:23 od [email protected]: > Hello, > > Gave this a try out of curiosity. I've been able to reproduce the bug > both on 7.8 and on current. Thank you for the detailed report and the > script, they helped a lot. :) > > The bug resides in a verification that the revision specified using the > -r parameter is not higher than the current head. The implementation is > incorrect, as it gives the same priority to major and minor versions. > E.g. 1.3 is being detected as higher than 2.2, since 2 < 3 on the minor > version. This is obviously incorrect. > > Due to this, the verification fails and the generic error that you see is > returned. > > The following diff should fix the issue both for rcsdiff and co. > > > Index: usr.bin/rcs/co.c > =================================================================== > RCS file: /cvs/src/usr.bin/rcs/co.c,v > diff -u -p -u -p -r1.127 co.c > --- usr.bin/rcs/co.c 11 Aug 2023 05:02:21 -0000 1.127 > +++ usr.bin/rcs/co.c 3 Jan 2026 23:57:04 -0000 > @@ -243,7 +243,6 @@ checkout_rev(RCSFILE *file, RCSNUM *frev > const char *date) > { > BUF *bp; > - u_int i; > int fd, lcount; > char buf[RCS_REV_BUFSZ]; > mode_t mode = DEFFILEMODE; > @@ -265,15 +264,10 @@ checkout_rev(RCSFILE *file, RCSNUM *frev > (void)fprintf(stderr, > "no revisions present; generating empty revision 0.0\n"); > - /* XXX rcsnum_cmp() > - * Check out the latest revision if <frev> is greater than HEAD > - */ > + /* Check out the latest revision if <frev> is greater than HEAD */ > if (file->rf_ndelta != 0) { > - for (i = 0; i < file->rf_head->rn_len; i++) { > - if (file->rf_head->rn_id[i] < frev->rn_id[i]) { > - frev = file->rf_head; > - break; > - } > + if (rcsnum_cmp(file->rf_head, frev, 0) == 1) { > + frev = file->rf_head; > } > } > Index: usr.bin/rcs/rcs.c > =================================================================== > RCS file: /cvs/src/usr.bin/rcs/rcs.c,v > diff -u -p -u -p -r1.89 rcs.c > --- usr.bin/rcs/rcs.c 28 Nov 2021 19:28:42 -0000 1.89 > +++ usr.bin/rcs/rcs.c 3 Jan 2026 23:57:04 -0000 > @@ -921,12 +921,9 @@ rcs_getrev(RCSFILE *rfp, RCSNUM *frev) > else > rev = frev; > - /* XXX rcsnum_cmp() */ > - for (i = 0; i < rfp->rf_head->rn_len; i++) { > - if (rfp->rf_head->rn_id[i] < rev->rn_id[i]) { > - rcs_errno = RCS_ERR_NOENT; > - return (NULL); > - } > + if (rcsnum_cmp(rfp->rf_head, rev, 0) == 1) { > + rcs_errno = RCS_ERR_NOENT; > + return (NULL); > } > /* No matter what, we'll need everything parsed up until the description > > > On 12/31/25 7:34 PM, Tomas Rippl wrote: > >> >> Hello, >> >> >> I believe I have found a bug in OpenRCS (base system) related to >> revision retrieval after changing the release number using `ci -r`. >> >> Environment: >> ------------ >> OpenBSD: OpenBSD srv-public.my.domain 7.8 GENERIC.MP#1 amd64 >> OpenRCS: OpenRCS 4.5 >> Program: co / rcsdiff >> >> Summary: >> -------- >> After creating a new release using `ci -r2.1`, older revisions on the >> trunk become unretrievable. Specifically, `rcsdiff` and `co -r` fail >> to retrieve revision 1.3, even though the revision exists, rlog shows >> a correct revision tree, and the deltatext is logically valid. >> >> This does not occur if the trunk continues normally (1.4, 1.5, ...); >> it only occurs after an explicit release-number jump using `ci -r2.1`. >> >> Minimal reproduction: >> --------------------- >> >> The following script reliably reproduces the problem: >> >> >> printf "a\n" >> z.txt >> ci -q -i -t-"test" -m"1.1" z.txt >> co -q -l z.txt >> printf "b\n" >> z.txt >> ci -q -u -m"1.2" z.txt >> co -q -l z.txt >> printf "c\n" >> z.txt >> ci -q -u -m"1.3" z.txt >> co -q -l z.txt >> printf "\nd\n" >> z.txt >> ci -q -r2.1 -m"2.1" z.txt >> co -q -l z.txt >> printf "e\n" >> z.txt >> ci -q -u -m"2.2" z.txt >> rcsdiff -r1.2 -r1.3 z.txt >> >> Observed result: >> ---------------- >> >> rcsdiff: failed to retrieve revision 1.3 >> >> Additional observations: >> ------------------------ >> - `rlog z.txt,v` shows a correct revision tree: >> 1.1 -> 1.2 -> 1.3 -> 2.1 -> 2.2 >> - The `next` chain in the RCS file is correct. >> - `co -p -r2.1` and `co -p -r2.2` work. >> - The deltatext for revision 1.3 is valid diff -n output. >> - The failure appears to be in revision reconstruction, not metadata. >> >> Control case (works as expected): >> --------------------------------- >> If the same history continues on the trunk without changing the >> release number, the problem does not occur: >> >> >> printf "\nd\n" >> z.txt >> ci -q -u -m"1.4" z.txt >> printf "e\n" >> z.txt >> ci -q -u -m"1.5" z.txt >> rcsdiff -r1.2 -r1.3 z.txt >> >> This correctly produces: >> >> diff -r1.2 -r1.3 >> 2a3 >> c >> >> Conclusion: >> ----------- >> It appears that after `ci -r2.1`, OpenRCS applies or selects deltas >> incorrectly when retrieving older trunk revisions, causing >> `rcsdiff` / `co` to fail even though the revision exists and its >> deltatext is consistent. >> >> Please let me know if you would like the generated `z.txt,v` file >> attached. >> >> Best regards, >> Tom >> >>
