Skip to content

Commit

Permalink
Fixed potential buffer overflow in SDL_vsnprintf() (thanks, Taylor!).
Browse files Browse the repository at this point in the history
Fixes Bugzilla #3441.

"When using internal SDL_vsnprintf(), and source string length is greater
than destination, the final NULL char will be written beyond destination size.

Primary issue that is SDL_strlcpy returns length of source string
(SDL_PrintString()), not how much is written to destination. The destination
ptr is then incremented by this length before the sanity check is done.
Destination string is properly terminated, but an extra NULL char will be
written beyond destination buffer length.

Patch used internally is attached which fixes primary issue with SDL_strlcpy()
in SDL_PrintString() and adjusts sanity checks to increment destination ptr
safely."
  • Loading branch information
icculus committed Oct 4, 2016
1 parent 351adf1 commit 46f44f6
Showing 1 changed file with 11 additions and 5 deletions.
16 changes: 11 additions & 5 deletions src/stdlib/SDL_string.c
Expand Up @@ -1315,6 +1315,7 @@ static size_t
SDL_PrintString(char *text, size_t maxlen, SDL_FormatInfo *info, const char *string)
{
size_t length = 0;
size_t slen;

if (info && info->width && (size_t)info->width > SDL_strlen(string)) {
char fill = info->pad_zeroes ? '0' : ' ';
Expand All @@ -1326,7 +1327,8 @@ SDL_PrintString(char *text, size_t maxlen, SDL_FormatInfo *info, const char *str
}
}

length += SDL_strlcpy(text, string, maxlen);
slen = SDL_strlcpy(text, string, maxlen);
length += SDL_min(slen, maxlen);

if (info) {
if (info->force_case == SDL_CASE_LOWER) {
Expand Down Expand Up @@ -1402,10 +1404,11 @@ SDL_PrintFloat(char *text, size_t maxlen, SDL_FormatInfo *info, double arg)
}
value = (unsigned long) arg;
len = SDL_PrintUnsignedLong(text, left, NULL, value);
text += len;
if (len >= left) {
text += (left > 1) ? left - 1 : 0;
left = SDL_min(left, 1);
} else {
text += len;
left -= len;
}
arg -= value;
Expand All @@ -1422,10 +1425,11 @@ SDL_PrintFloat(char *text, size_t maxlen, SDL_FormatInfo *info, double arg)
while (info->precision-- > 0) {
value = (unsigned long) (arg * mult);
len = SDL_PrintUnsignedLong(text, left, NULL, value);
text += len;
if (len >= left) {
text += (left > 1) ? left - 1 : 0;
left = SDL_min(left, 1);
} else {
text += len;
left -= len;
}
arg -= (double) value / mult;
Expand Down Expand Up @@ -1458,10 +1462,11 @@ SDL_PrintFloat(char *text, size_t maxlen, SDL_FormatInfo *info, double arg)
}
}
len = (size_t)width;
text += len;
if (len >= left) {
text += (left > 1) ? left - 1 : 0;
left = SDL_min(left, 1);
} else {
text += len;
left -= len;
}
while (len--) {
Expand Down Expand Up @@ -1637,10 +1642,11 @@ SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt,
}
++fmt;
}
text += len;
if (len >= left) {
text += (left > 1) ? left - 1 : 0;
left = SDL_min(left, 1);
} else {
text += len;
left -= len;
}
} else {
Expand Down

0 comments on commit 46f44f6

Please sign in to comment.