Skip to content

Commit

Permalink
patch 9.1.0912: xxd: integer overflow with sparse files and -autoskip
Browse files Browse the repository at this point in the history
Problem:  xxd: integer overflow with sparse files and -autoskip
Solution: reset zero_seen when at the limit, change the type to char
          (sendittothenewts)

When encountering INT_MAX lines of zeros in the input, xxd overflows an
`int` counter, resulting in undefined behaviour.  Usually, this results
in a spurious line of zeros being output every 2**32 lines, while the
"*" line is lost, as is the final line of zeros that delineate the file
size if at end of file.

Since xxd doesn't need to know exactly how many lines are being skipped
when it's > 3, the exact value of the line counter `zero_seen` doesn't
matter and it can simply be reduced in value before the overflow occurs.

Changing the type of `zero_seen` to `signed char` is not important, and
done only to make the bug triggerable with more modest file sizes, and
therefore more convenient to test the fix.

fixes: vim#16170
closes: vim#16175

Signed-off-by: sendittothenewts <[email protected]>
Signed-off-by: Christian Brabandt <[email protected]>
  • Loading branch information
sendittothenewts authored and chrisbra committed Dec 7, 2024
1 parent 8cc43da commit 6e6aff0
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/version.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
/**/
912,
/**/
911,
/**/
Expand Down
12 changes: 9 additions & 3 deletions src/xxd/xxd.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
* 10.09.2024 Support -b and -i together, #15661
* 19.10.2024 -e did add an extra space #15899
* 11.11.2024 improve end-of-options argument parser #9285
* 07.12.2024 fix overflow with xxd --autoskip and large sparse files #16175
*
* (c) 1990-1998 by Juergen Weigert ([email protected])
*
Expand Down Expand Up @@ -146,7 +147,7 @@ extern void perror __P((char *));
# endif
#endif

char version[] = "xxd 2024-11-11 by Juergen Weigert et al.";
char version[] = "xxd 2024-12-07 by Juergen Weigert et al.";
#ifdef WIN32
char osver[] = " (Win32)";
#else
Expand Down Expand Up @@ -515,7 +516,7 @@ huntype(
}

/*
* Print line l. If nz is false, xxdline regards the line a line of
* Print line l. If nz is false, xxdline regards the line as a line of
* zeroes. If there are three or more consecutive lines of zeroes,
* they are replaced by a single '*' character.
*
Expand All @@ -530,7 +531,7 @@ huntype(
xxdline(FILE *fp, char *l, int nz)
{
static char z[LLEN+1];
static int zero_seen = 0;
static signed char zero_seen = 0;

if (!nz && zero_seen == 1)
strcpy(z, l);
Expand All @@ -551,6 +552,11 @@ xxdline(FILE *fp, char *l, int nz)
if (nz)
zero_seen = 0;
}

/* If zero_seen > 3, then its exact value doesn't matter, so long as it
* remains >3 and incrementing it will not cause overflow. */
if (zero_seen >= 0x7F)
zero_seen = 4;
}

/* This is an EBCDIC to ASCII conversion table */
Expand Down

0 comments on commit 6e6aff0

Please sign in to comment.