aboutsummaryrefslogtreecommitdiff
path: root/Tremolo/res012.c
diff options
context:
space:
mode:
Diffstat (limited to 'Tremolo/res012.c')
-rw-r--r--Tremolo/res012.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/Tremolo/res012.c b/Tremolo/res012.c
index d6495fb..ac09671 100644
--- a/Tremolo/res012.c
+++ b/Tremolo/res012.c
@@ -65,9 +65,9 @@ int res_unpack(vorbis_info_residue *info,
if(info->type>2 || info->type<0)goto errout;
info->begin=oggpack_read(opb,24);
info->end=oggpack_read(opb,24);
- info->grouping=oggpack_read(opb,24)+1;
- info->partitions=(char)(oggpack_read(opb,6)+1);
- info->groupbook=(unsigned char)oggpack_read(opb,8);
+ info->grouping=oggpack_read(opb,24)+1; // "partition size" in spec
+ info->partitions=(char)(oggpack_read(opb,6)+1); // "classification" in spec
+ info->groupbook=(unsigned char)oggpack_read(opb,8); // "classbook" in spec
if(info->groupbook>=ci->books)goto errout;
info->stagemasks=_ogg_malloc(info->partitions*sizeof(*info->stagemasks));
@@ -94,6 +94,15 @@ int res_unpack(vorbis_info_residue *info,
if(oggpack_eop(opb))goto errout;
+ // According to the Vorbis spec (paragraph 8.6.2 "packet decode"), residue
+ // begin and end should be limited to the maximum possible vector size in
+ // case they exceed it. However doing that makes the decoder crash further
+ // down, so we return an error instead.
+ int limit = (info->type == 2 ? vi->channels : 1) * ci->blocksizes[1] / 2;
+ if (info->begin > info->end ||
+ info->end > limit) {
+ goto errout;
+ }
return 0;
errout:
res_clear_info(info);