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
>>
>>

Reply via email to