Skip to content

Commit 98fdfc6

Browse files
author
Sean Barrett
committed
Fix seven bugs discovered and fixed by ForAllSecure:
CVE-2019-13217: heap buffer overflow in start_decoder() CVE-2019-13218: stack buffer overflow in compute_codewords() CVE-2019-13219: uninitialized memory in vorbis_decode_packet_rest() CVE-2019-13220: out-of-range read in draw_line() CVE-2019-13221: issue with large 1D codebooks in lookup1_values() CVE-2019-13222: unchecked NULL returned by get_window() CVE-2019-13223: division by zero in predict_point()
1 parent c72a95d commit 98fdfc6

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

Diff for: stb_vorbis.c

+22-6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
// Timur Gagiev
3434
//
3535
// Partial history:
36+
// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure)
3637
// 1.16 - 2019-03-04 - fix warnings
3738
// 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found
3839
// 1.14 - 2018-02-11 - delete bogus dealloca usage
@@ -1202,8 +1203,10 @@ static int lookup1_values(int entries, int dim)
12021203
int r = (int) floor(exp((float) log((float) entries) / dim));
12031204
if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning;
12041205
++r; // floor() to avoid _ftol() when non-CRT
1205-
assert(pow((float) r+1, dim) > entries);
1206-
assert((int) floor(pow((float) r, dim)) <= entries); // (int),floor() as above
1206+
if (pow((float) r+1, dim) <= entries)
1207+
return -1;
1208+
if ((int) floor(pow((float) r, dim)) > entries)
1209+
return -1;
12071210
return r;
12081211
}
12091212

@@ -2013,15 +2016,15 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y
20132016
ady -= abs(base) * adx;
20142017
if (x1 > n) x1 = n;
20152018
if (x < x1) {
2016-
LINE_OP(output[x], inverse_db_table[y]);
2019+
LINE_OP(output[x], inverse_db_table[y&255]);
20172020
for (++x; x < x1; ++x) {
20182021
err += ady;
20192022
if (err >= adx) {
20202023
err -= adx;
20212024
y += sy;
20222025
} else
20232026
y += base;
2024-
LINE_OP(output[x], inverse_db_table[y]);
2027+
LINE_OP(output[x], inverse_db_table[y&255]);
20252028
}
20262029
}
20272030
}
@@ -3048,7 +3051,6 @@ static float *get_window(vorb *f, int len)
30483051
len <<= 1;
30493052
if (len == f->blocksize_0) return f->window[0];
30503053
if (len == f->blocksize_1) return f->window[1];
3051-
assert(0);
30523054
return NULL;
30533055
}
30543056

@@ -3454,6 +3456,7 @@ static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right)
34543456
if (f->previous_length) {
34553457
int i,j, n = f->previous_length;
34563458
float *w = get_window(f, n);
3459+
if (w == NULL) return 0;
34573460
for (i=0; i < f->channels; ++i) {
34583461
for (j=0; j < n; ++j)
34593462
f->channel_buffers[i][left+j] =
@@ -3695,6 +3698,7 @@ static int start_decoder(vorb *f)
36953698
while (current_entry < c->entries) {
36963699
int limit = c->entries - current_entry;
36973700
int n = get_bits(f, ilog(limit));
3701+
if (current_length >= 32) return error(f, VORBIS_invalid_setup);
36983702
if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); }
36993703
memset(lengths + current_entry, current_length, n);
37003704
current_entry += n;
@@ -3798,7 +3802,9 @@ static int start_decoder(vorb *f)
37983802
c->value_bits = get_bits(f, 4)+1;
37993803
c->sequence_p = get_bits(f,1);
38003804
if (c->lookup_type == 1) {
3801-
c->lookup_values = lookup1_values(c->entries, c->dimensions);
3805+
int values = lookup1_values(c->entries, c->dimensions);
3806+
if (values < 0) return error(f, VORBIS_invalid_setup);
3807+
c->lookup_values = (uint32) values;
38023808
} else {
38033809
c->lookup_values = c->entries * c->dimensions;
38043810
}
@@ -3934,6 +3940,9 @@ static int start_decoder(vorb *f)
39343940
p[j].id = j;
39353941
}
39363942
qsort(p, g->values, sizeof(p[0]), point_compare);
3943+
for (j=0; j < g->values-1; ++j)
3944+
if (p[j].x == p[j+1].x)
3945+
return error(f, VORBIS_invalid_setup);
39373946
for (j=0; j < g->values; ++j)
39383947
g->sorted_order[j] = (uint8) p[j].id;
39393948
// precompute the neighbors
@@ -4020,6 +4029,7 @@ static int start_decoder(vorb *f)
40204029
max_submaps = m->submaps;
40214030
if (get_bits(f,1)) {
40224031
m->coupling_steps = get_bits(f,8)+1;
4032+
if (m->coupling_steps > f->channels) return error(f, VORBIS_invalid_setup);
40234033
for (k=0; k < m->coupling_steps; ++k) {
40244034
m->chan[k].magnitude = get_bits(f, ilog(f->channels-1));
40254035
m->chan[k].angle = get_bits(f, ilog(f->channels-1));
@@ -5386,6 +5396,12 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in
53865396
#endif // STB_VORBIS_NO_PULLDATA_API
53875397

53885398
/* Version history
5399+
1.17 - 2019-07-08 - fix CVE-2019-13217, -13218, -13219, -13220, -13221, -13223, -13223
5400+
found with Mayhem by ForAllSecure
5401+
1.16 - 2019-03-04 - fix warnings
5402+
1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found
5403+
1.14 - 2018-02-11 - delete bogus dealloca usage
5404+
1.13 - 2018-01-29 - fix truncation of last frame (hopefully)
53895405
1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
53905406
1.11 - 2017-07-23 - fix MinGW compilation
53915407
1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory

0 commit comments

Comments
 (0)