Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix a possible format overflow in dump_genid() #571

Merged
merged 1 commit into from
Jul 11, 2024

Conversation

ppisar
Copy link
Contributor

@ppisar ppisar commented Jul 10, 2024

GCC 14 called with CFLAGS='-O2 -Wformat-overflow' complains:

/tmp/libsolv/ext/testcase.c: In function ‘dump_genid’:
/tmp/libsolv/ext/testcase.c:1275:33: warning: ‘: genid ’ directive writing 8 bytes into a region of size between 3 and 12 [-Wformat-overflow=]
 1275 |       sprintf(cntbuf, "genid %2d: genid ", cnt++);
  |                                 ^~~~~~~~
/tmp/libsolv/ext/testcase.c:1275:7: note: ‘sprintf’ output between 17 and 26 bytes into a destination of size 20
 1275 |       sprintf(cntbuf, "genid %2d: genid ", cnt++);
  |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/libsolv/ext/testcase.c:1270:33: warning: ‘: genid ’ directive writing 8 bytes into a region of size between 3 and 12 [-Wformat-overflow=]
 1270 |       sprintf(cntbuf, "genid %2d: genid ", cnt++);
  |                                 ^~~~~~~~
/tmp/libsolv/ext/testcase.c:1270:7: note: ‘sprintf’ output between 17 and 26 bytes into a destination of size 20
 1270 |       sprintf(cntbuf, "genid %2d: genid ", cnt++);
  |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

That's indeed a bug: sprintf() writes into a 20-byte array cntbuf. cnt is int, 32-bit long integer on x86_64 Linux platform. dump_genid() starts with cnt = 1 and increases. It can go up to 2147483647 decimal value, then wrap to -2147483648 decimal value. That's up to 11 bytes of the integer, plus 14 bytes of a static string, plus 1 byte of a trailing '\0'. 26 bytes in total.

While it's improbable that cnt would amount that long number in real life, it's better to be prepared for the worst. Also a benefit is that static analyzers will be be content.

This patch increases cntbuf[] size to accomodate common 32-bit ints. (Generic, albeit illegible, expression would be:

cntbuf[((sizeof(cnt) * 8 - 1) * 3 / 10 + 1 + 1) + 14 + 1];

but I'm not sure that long expression is worth of it.)

GCC 14 called with CFLAGS='-O2 -Wformat-overflow' complains:

    /tmp/libsolv/ext/testcase.c: In function ‘dump_genid’:
    /tmp/libsolv/ext/testcase.c:1275:33: warning: ‘: genid ’ directive writing 8 bytes into a region of size between 3 and 12 [-Wformat-overflow=]
     1275 |       sprintf(cntbuf, "genid %2d: genid ", cnt++);
	  |                                 ^~~~~~~~
    /tmp/libsolv/ext/testcase.c:1275:7: note: ‘sprintf’ output between 17 and 26 bytes into a destination of size 20
     1275 |       sprintf(cntbuf, "genid %2d: genid ", cnt++);
	  |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /tmp/libsolv/ext/testcase.c:1270:33: warning: ‘: genid ’ directive writing 8 bytes into a region of size between 3 and 12 [-Wformat-overflow=]
     1270 |       sprintf(cntbuf, "genid %2d: genid ", cnt++);
	  |                                 ^~~~~~~~
    /tmp/libsolv/ext/testcase.c:1270:7: note: ‘sprintf’ output between 17 and 26 bytes into a destination of size 20
     1270 |       sprintf(cntbuf, "genid %2d: genid ", cnt++);
	  |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

That's indeed a bug: sprintf() writes into a 20-byte array cntbuf. cnt
is int, 32-bit long integer on x86_64 Linux platform. dump_genid()
starts with cnt = 1 and increases. It can go up to 2147483647 decimal
value, then wrap to -2147483648 decimal value.  That's up to 11 bytes
of the integer, plus 14 bytes of a static string, plus 1 byte of
a trailing '\0'. 26 bytes in total.

While it's improbable that cnt would amount that long number in real
life, it's better to be prepared for the worst. Also a benefit is that
static analyzers will be be content.

This patch increases cntbuf[] size to accomodate common 32-bit
ints. (Generic, albeit illegible, expression would be:

    cntbuf[((sizeof(cnt) * 8 - 1) * 3 / 10 + 1 + 1) + 14 + 1];

but I'm not sure that long expression is worth of it.)
@mlschroe
Copy link
Member

Right, thanks for the patch!

@mlschroe mlschroe merged commit 00db74a into openSUSE:master Jul 11, 2024
1 check passed
@mlschroe
Copy link
Member

(dump_genid() is only a debugging aid, so this is not security relevant)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants