|
@@ -1,4 +1,4 @@
|
|
|
-// Ogg Vorbis audio decoder - v1.14 - public domain
|
|
|
+// Ogg Vorbis audio decoder - v1.17 - public domain
|
|
|
// http://nothings.org/stb_vorbis/
|
|
|
//
|
|
|
// Original version written by Sean Barrett in 2007.
|
|
@@ -30,9 +30,12 @@
|
|
|
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
|
|
|
// Phillip Bennefall Rohit Thiago Goulart
|
|
|
// manxorist@github saga musix github:infatum
|
|
|
-// Timur Gagiev
|
|
|
+// Timur Gagiev Maxwell Koo
|
|
|
//
|
|
|
// Partial history:
|
|
|
+// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure)
|
|
|
+// 1.16 - 2019-03-04 - fix warnings
|
|
|
+// 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found
|
|
|
// 1.14 - 2018-02-11 - delete bogus dealloca usage
|
|
|
// 1.13 - 2018-01-29 - fix truncation of last frame (hopefully)
|
|
|
// 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
|
|
@@ -255,7 +258,7 @@ extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
|
|
|
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
|
|
// the _current_ seek point (ftell). on failure, returns NULL and sets *error.
|
|
|
// note that stb_vorbis must "own" this stream; if you seek it in between
|
|
|
-// calls to stb_vorbis, it will become confused. Morever, if you attempt to
|
|
|
+// calls to stb_vorbis, it will become confused. Moreover, if you attempt to
|
|
|
// perform stb_vorbis_seek_*() operations on this file, it will assume it
|
|
|
// owns the _entire_ rest of the file after the start point. Use the next
|
|
|
// function, stb_vorbis_open_file_section(), to limit it.
|
|
@@ -376,7 +379,8 @@ enum STBVorbisError
|
|
|
VORBIS_invalid_first_page,
|
|
|
VORBIS_bad_packet_type,
|
|
|
VORBIS_cant_find_last_page,
|
|
|
- VORBIS_seek_failed
|
|
|
+ VORBIS_seek_failed,
|
|
|
+ VORBIS_ogg_skeleton_not_supported
|
|
|
};
|
|
|
|
|
|
|
|
@@ -1075,7 +1079,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
|
|
|
assert(z >= 0 && z < 32);
|
|
|
available[z] = 0;
|
|
|
add_entry(c, bit_reverse(res), i, m++, len[i], values);
|
|
|
- // propogate availability up the tree
|
|
|
+ // propagate availability up the tree
|
|
|
if (z != len[i]) {
|
|
|
assert(len[i] >= 0 && len[i] < 32);
|
|
|
for (y=len[i]; y > z; --y) {
|
|
@@ -1201,8 +1205,10 @@ static int lookup1_values(int entries, int dim)
|
|
|
int r = (int) floor(exp((float) log((float) entries) / dim));
|
|
|
if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning;
|
|
|
++r; // floor() to avoid _ftol() when non-CRT
|
|
|
- assert(pow((float) r+1, dim) > entries);
|
|
|
- assert((int) floor(pow((float) r, dim)) <= entries); // (int),floor() as above
|
|
|
+ if (pow((float) r+1, dim) <= entries)
|
|
|
+ return -1;
|
|
|
+ if ((int) floor(pow((float) r, dim)) > entries)
|
|
|
+ return -1;
|
|
|
return r;
|
|
|
}
|
|
|
|
|
@@ -2012,7 +2018,7 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y
|
|
|
ady -= abs(base) * adx;
|
|
|
if (x1 > n) x1 = n;
|
|
|
if (x < x1) {
|
|
|
- LINE_OP(output[x], inverse_db_table[y]);
|
|
|
+ LINE_OP(output[x], inverse_db_table[y&255]);
|
|
|
for (++x; x < x1; ++x) {
|
|
|
err += ady;
|
|
|
if (err >= adx) {
|
|
@@ -2020,7 +2026,7 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y
|
|
|
y += sy;
|
|
|
} else
|
|
|
y += base;
|
|
|
- LINE_OP(output[x], inverse_db_table[y]);
|
|
|
+ LINE_OP(output[x], inverse_db_table[y&255]);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -2639,7 +2645,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
|
|
|
// once I combined the passes.
|
|
|
|
|
|
// so there's a missing 'times 2' here (for adding X to itself).
|
|
|
- // this propogates through linearly to the end, where the numbers
|
|
|
+ // this propagates through linearly to the end, where the numbers
|
|
|
// are 1/2 too small, and need to be compensated for.
|
|
|
|
|
|
{
|
|
@@ -3047,7 +3053,6 @@ static float *get_window(vorb *f, int len)
|
|
|
len <<= 1;
|
|
|
if (len == f->blocksize_0) return f->window[0];
|
|
|
if (len == f->blocksize_1) return f->window[1];
|
|
|
- assert(0);
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
@@ -3453,6 +3458,7 @@ static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right)
|
|
|
if (f->previous_length) {
|
|
|
int i,j, n = f->previous_length;
|
|
|
float *w = get_window(f, n);
|
|
|
+ if (w == NULL) return 0;
|
|
|
for (i=0; i < f->channels; ++i) {
|
|
|
for (j=0; j < n; ++j)
|
|
|
f->channel_buffers[i][left+j] =
|
|
@@ -3580,7 +3586,22 @@ static int start_decoder(vorb *f)
|
|
|
if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page);
|
|
|
// check for expected packet length
|
|
|
if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page);
|
|
|
- if (f->segments[0] != 30) return error(f, VORBIS_invalid_first_page);
|
|
|
+ if (f->segments[0] != 30) {
|
|
|
+ // check for the Ogg skeleton fishead identifying header to refine our error
|
|
|
+ if (f->segments[0] == 64 &&
|
|
|
+ getn(f, header, 6) &&
|
|
|
+ header[0] == 'f' &&
|
|
|
+ header[1] == 'i' &&
|
|
|
+ header[2] == 's' &&
|
|
|
+ header[3] == 'h' &&
|
|
|
+ header[4] == 'e' &&
|
|
|
+ header[5] == 'a' &&
|
|
|
+ get8(f) == 'd' &&
|
|
|
+ get8(f) == '\0') return error(f, VORBIS_ogg_skeleton_not_supported);
|
|
|
+ else
|
|
|
+ return error(f, VORBIS_invalid_first_page);
|
|
|
+ }
|
|
|
+
|
|
|
// read packet
|
|
|
// check packet header
|
|
|
if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page);
|
|
@@ -3679,6 +3700,7 @@ static int start_decoder(vorb *f)
|
|
|
while (current_entry < c->entries) {
|
|
|
int limit = c->entries - current_entry;
|
|
|
int n = get_bits(f, ilog(limit));
|
|
|
+ if (current_length >= 32) return error(f, VORBIS_invalid_setup);
|
|
|
if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); }
|
|
|
memset(lengths + current_entry, current_length, n);
|
|
|
current_entry += n;
|
|
@@ -3782,7 +3804,9 @@ static int start_decoder(vorb *f)
|
|
|
c->value_bits = get_bits(f, 4)+1;
|
|
|
c->sequence_p = get_bits(f,1);
|
|
|
if (c->lookup_type == 1) {
|
|
|
- c->lookup_values = lookup1_values(c->entries, c->dimensions);
|
|
|
+ int values = lookup1_values(c->entries, c->dimensions);
|
|
|
+ if (values < 0) return error(f, VORBIS_invalid_setup);
|
|
|
+ c->lookup_values = (uint32) values;
|
|
|
} else {
|
|
|
c->lookup_values = c->entries * c->dimensions;
|
|
|
}
|
|
@@ -3918,6 +3942,9 @@ static int start_decoder(vorb *f)
|
|
|
p[j].id = j;
|
|
|
}
|
|
|
qsort(p, g->values, sizeof(p[0]), point_compare);
|
|
|
+ for (j=0; j < g->values-1; ++j)
|
|
|
+ if (p[j].x == p[j+1].x)
|
|
|
+ return error(f, VORBIS_invalid_setup);
|
|
|
for (j=0; j < g->values; ++j)
|
|
|
g->sorted_order[j] = (uint8) p[j].id;
|
|
|
// precompute the neighbors
|
|
@@ -4004,6 +4031,7 @@ static int start_decoder(vorb *f)
|
|
|
max_submaps = m->submaps;
|
|
|
if (get_bits(f,1)) {
|
|
|
m->coupling_steps = get_bits(f,8)+1;
|
|
|
+ if (m->coupling_steps > f->channels) return error(f, VORBIS_invalid_setup);
|
|
|
for (k=0; k < m->coupling_steps; ++k) {
|
|
|
m->chan[k].magnitude = get_bits(f, ilog(f->channels-1));
|
|
|
m->chan[k].angle = get_bits(f, ilog(f->channels-1));
|
|
@@ -4568,7 +4596,7 @@ static int get_seek_page_info(stb_vorbis *f, ProbedPage *z)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
-// rarely used function to seek back to the preceeding page while finding the
|
|
|
+// rarely used function to seek back to the preceding page while finding the
|
|
|
// start of a packet
|
|
|
static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset)
|
|
|
{
|
|
@@ -4975,7 +5003,13 @@ stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, con
|
|
|
|
|
|
stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc)
|
|
|
{
|
|
|
- FILE *f = fopen(filename, "rb");
|
|
|
+ FILE *f;
|
|
|
+#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__)
|
|
|
+ if (0 != fopen_s(&f, filename, "rb"))
|
|
|
+ f = NULL;
|
|
|
+#else
|
|
|
+ f = fopen(filename, "rb");
|
|
|
+#endif
|
|
|
if (f)
|
|
|
return stb_vorbis_open_file(f, TRUE, error, alloc);
|
|
|
if (error) *error = VORBIS_file_open_failure;
|
|
@@ -5364,6 +5398,12 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in
|
|
|
#endif // STB_VORBIS_NO_PULLDATA_API
|
|
|
|
|
|
/* Version history
|
|
|
+ 1.17 - 2019-07-08 - fix CVE-2019-13217, -13218, -13219, -13220, -13221, -13222, -13223
|
|
|
+ found with Mayhem by ForAllSecure
|
|
|
+ 1.16 - 2019-03-04 - fix warnings
|
|
|
+ 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found
|
|
|
+ 1.14 - 2018-02-11 - delete bogus dealloca usage
|
|
|
+ 1.13 - 2018-01-29 - fix truncation of last frame (hopefully)
|
|
|
1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
|
|
|
1.11 - 2017-07-23 - fix MinGW compilation
|
|
|
1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory
|