Add more overflow checks to cuesheet parsing

Credit: Oss-Fuzz
Issue: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=57315
This commit is contained in:
Martijn van Beurden 2023-04-18 11:07:22 +02:00
parent 1faa4924e2
commit 29d1460a38
1 changed files with 60 additions and 26 deletions

View File

@ -24,6 +24,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "FLAC/assert.h"
#include "share/compat.h"
#include "share/grabbag.h"
@ -43,24 +44,6 @@ void grabbag__cuesheet_frame_to_msf(uint32_t frame, uint32_t *minutes, uint32_t
*minutes = frame;
}
/* since we only care about values >= 0 or error, returns < 0 for any illegal string, else value */
static int local__parse_int_(const char *s)
{
int ret = 0;
char c;
if(*s == '\0')
return -1;
while('\0' != (c = *s++))
if(c >= '0' && c <= '9')
ret = ret * 10 + (c - '0');
else
return -1;
return ret;
}
/* since we only care about values >= 0 or error, returns < 0 for any illegal string, else value */
static FLAC__int64 local__parse_int64_(const char *s)
{
@ -71,14 +54,33 @@ static FLAC__int64 local__parse_int64_(const char *s)
return -1;
while('\0' != (c = *s++))
if(c >= '0' && c <= '9')
ret = ret * 10 + (c - '0');
if(c >= '0' && c <= '9') {
if(ret > (INT64_MAX / 10))
return false;
else if(ret == (INT64_MAX/10)) {
FLAC__int64 tmp = ret;
ret = ret * 10 + (c - '0');
if(ret < tmp)
return -1;
}
else
ret = ret * 10 + (c - '0');
}
else
return -1;
return ret;
}
/* since we only care about values >= 0 or error, returns < 0 for any illegal string, else value */
static int local__parse_int_(const char *s)
{
FLAC__int64 ret64 = local__parse_int64_(s);
if(ret64 < 0 || ret64 > INT_MAX)
return -1;
return ret64;
}
/* accept minute:second:frame syntax of '[0-9]+:[0-9][0-9]?:[0-9][0-9]?', but max second of 59 and max frame of 74, e.g. 0:0:0, 123:45:67
* return sample number or <0 for error
* WATCHOUT: if sample rate is not evenly divisible by 75, the resulting sample number will be approximate
@ -94,12 +96,24 @@ static FLAC__int64 local__parse_msf_(const char *s, uint32_t sample_rate)
else
return -1;
while(':' != (c = *s++)) {
if(c >= '0' && c <= '9')
field = field * 10 + (c - '0');
if(c >= '0' && c <= '9') {
if(field > (INT64_MAX / 10))
return false;
else if(field == (INT64_MAX/10)) {
FLAC__int64 tmp = field;
field = field * 10 + (c - '0');
if(field < tmp)
return -1;
}
else
field = field * 10 + (c - '0');
}
else
return -1;
}
if(field > INT64_MAX / (60 * sample_rate))
return -1;
ret = field * 60 * sample_rate;
c = *s++;
@ -121,7 +135,12 @@ static FLAC__int64 local__parse_msf_(const char *s, uint32_t sample_rate)
if(field >= 60)
return -1;
ret += field * sample_rate;
{
FLAC__int64 tmp = ret;
ret += field * sample_rate;
if(ret < tmp)
return -1;
}
c = *s++;
if(c >= '0' && c <= '9')
@ -143,7 +162,12 @@ static FLAC__int64 local__parse_msf_(const char *s, uint32_t sample_rate)
if(field >= 75)
return -1;
ret += field * (sample_rate / 75);
{
FLAC__int64 tmp = ret;
ret += field * (sample_rate / 75);
if(ret < tmp)
return -1;
}
return ret;
}
@ -164,8 +188,18 @@ static FLAC__int64 local__parse_ms_(const char *s, uint32_t sample_rate)
else
return -1;
while(':' != (c = *s++)) {
if(c >= '0' && c <= '9')
field = field * 10 + (c - '0');
if(c >= '0' && c <= '9') {
if(field > (INT64_MAX / 10))
return false;
else if(field == (INT64_MAX/10)) {
FLAC__int64 tmp = field;
field = field * 10 + (c - '0');
if(field < tmp)
return -1;
}
else
field = field * 10 + (c - '0');
}
else
return -1;
}