reject vorbis comments with negative loop parameters (bug #4905)
authorOzkan Sezer
Thu, 19 Dec 2019 18:55:02 +0300
changeset 1099a3c637d1a698
parent 1098 3be892f72aa7
child 1100 ba8b8227a7bd
reject vorbis comments with negative loop parameters (bug #4905)

Also simplify music->loop decision, change FLAC_Music->loop_start,
loop_len, loop_end, pcm_pos and full_length members to signed type.
src/codecs/music_flac.c
src/codecs/music_ogg.c
src/codecs/music_opus.c
     1.1 --- a/src/codecs/music_flac.c	Wed Dec 18 18:55:56 2019 +0300
     1.2 +++ b/src/codecs/music_flac.c	Thu Dec 19 18:55:02 2019 +0300
     1.3 @@ -155,12 +155,12 @@
     1.4      int freesrc;
     1.5      SDL_AudioStream *stream;
     1.6      int loop;
     1.7 -    FLAC__uint64 pcm_pos;
     1.8 -    FLAC__uint64 full_length;
     1.9 +    FLAC__int64 pcm_pos;
    1.10 +    FLAC__int64 full_length;
    1.11      SDL_bool loop_flag;
    1.12 -    FLAC__uint64 loop_start;
    1.13 -    FLAC__uint64 loop_end;
    1.14 -    FLAC__uint64 loop_len;
    1.15 +    FLAC__int64 loop_start;
    1.16 +    FLAC__int64 loop_end;
    1.17 +    FLAC__int64 loop_len;
    1.18  } FLAC_Music;
    1.19  
    1.20  
    1.21 @@ -351,7 +351,7 @@
    1.22          }
    1.23      }
    1.24      amount = (int)(frame->header.blocksize * channels * sizeof(*data));
    1.25 -    music->pcm_pos += (FLAC__uint64) frame->header.blocksize;
    1.26 +    music->pcm_pos += (FLAC__int64) frame->header.blocksize;
    1.27      if ((music->loop == 1) && (music->play_count != 1) &&
    1.28          (music->pcm_pos >= music->loop_end)) {
    1.29          amount -= (music->pcm_pos - music->loop_end) * channels * sizeof(*data);
    1.30 @@ -366,15 +366,15 @@
    1.31  
    1.32  /* Parse time string of the form HH:MM:SS.mmm and return equivalent sample
    1.33   * position */
    1.34 -static FLAC__uint64 parse_time(char *time, unsigned samplerate_hz)
    1.35 +static FLAC__int64 parse_time(char *time, unsigned samplerate_hz)
    1.36  {
    1.37      char *num_start, *p;
    1.38 -    FLAC__uint64 result = 0;
    1.39 -    char c;
    1.40 +    FLAC__int64 result = 0;
    1.41 +    char c; int val;
    1.42  
    1.43      /* Time is directly expressed as a sample position */
    1.44      if (SDL_strchr(time, ':') == NULL) {
    1.45 -        return SDL_strtoull(time, NULL, 10);
    1.46 +        return SDL_strtoll(time, NULL, 10);
    1.47      }
    1.48  
    1.49      result = 0;
    1.50 @@ -383,18 +383,22 @@
    1.51      for (p = time; *p != '\0'; ++p) {
    1.52          if (*p == '.' || *p == ':') {
    1.53              c = *p; *p = '\0';
    1.54 -            result = result * 60 + SDL_atoi(num_start);
    1.55 +            if ((val = SDL_atoi(num_start)) < 0)
    1.56 +                return -1;
    1.57 +            result = result * 60 + val;
    1.58              num_start = p + 1;
    1.59              *p = c;
    1.60          }
    1.61  
    1.62          if (*p == '.') {
    1.63 -            return result * samplerate_hz
    1.64 -                + (FLAC__uint64) (SDL_atof(p) * samplerate_hz);
    1.65 +            double val_f = SDL_atof(p);
    1.66 +            if (val_f < 0) return -1;
    1.67 +            return result * samplerate_hz + (FLAC__int64) (val_f * samplerate_hz);
    1.68          }
    1.69      }
    1.70  
    1.71 -    return (result * 60 + SDL_atoi(num_start)) * samplerate_hz;
    1.72 +    if ((val = SDL_atoi(num_start)) < 0) return -1;
    1.73 +    return (result * 60 + val) * samplerate_hz;
    1.74  }
    1.75  
    1.76  static void flac_metadata_music_cb(
    1.77 @@ -449,21 +453,26 @@
    1.78  
    1.79              /* Want to match LOOP-START, LOOP_START, etc. Remove - or _ from
    1.80               * string if it is present at position 4. */
    1.81 -
    1.82              if ((argument[4] == '_') || (argument[4] == '-')) {
    1.83 -                SDL_memmove(argument + 4, argument + 5,
    1.84 -                           SDL_strlen(argument) - 4);
    1.85 +                SDL_memmove(argument + 4, argument + 5, SDL_strlen(argument) - 4);
    1.86              }
    1.87  
    1.88              if (SDL_strcasecmp(argument, "LOOPSTART") == 0)
    1.89                  music->loop_start = parse_time(value, rate);
    1.90              else if (SDL_strcasecmp(argument, "LOOPLENGTH") == 0) {
    1.91 -                music->loop_len = SDL_strtoull(value, NULL, 10);
    1.92 +                music->loop_len = SDL_strtoll(value, NULL, 10);
    1.93                  is_loop_length = SDL_TRUE;
    1.94              } else if (SDL_strcasecmp(argument, "LOOPEND") == 0) {
    1.95                  music->loop_end = parse_time(value, rate);
    1.96                  is_loop_length = SDL_FALSE;
    1.97              }
    1.98 +            if (music->loop_start < 0 || music->loop_len < 0 || music->loop_end < 0) {
    1.99 +                music->loop_start = 0;
   1.100 +                music->loop_len = 0;
   1.101 +                music->loop_end = 0;
   1.102 +                SDL_free(param);
   1.103 +                break;  /* ignore tag. */
   1.104 +            }
   1.105              SDL_free(param);
   1.106          }
   1.107  
   1.108 @@ -509,7 +518,7 @@
   1.109      FLAC_Music *music;
   1.110      int init_stage = 0;
   1.111      int was_error = 1;
   1.112 -    FLAC__uint64 full_length;
   1.113 +    FLAC__int64 full_length;
   1.114  
   1.115      music = (FLAC_Music *)SDL_calloc(1, sizeof(*music));
   1.116      if (!music) {
   1.117 @@ -519,11 +528,6 @@
   1.118      music->src = src;
   1.119      music->volume = MIX_MAX_VOLUME;
   1.120      music->loop = -1;
   1.121 -    music->loop_start = -1;
   1.122 -    music->loop_end = 0;
   1.123 -    music->loop_len = 0;
   1.124 -    music->loop_flag = SDL_FALSE;
   1.125 -    music->pcm_pos = 0;
   1.126  
   1.127      music->flac_decoder = flac.FLAC__stream_decoder_new();
   1.128      if (music->flac_decoder) {
   1.129 @@ -568,13 +572,9 @@
   1.130      /* loop_start, loop_end and loop_len get set by metadata callback if tags
   1.131       * are present in metadata.
   1.132       */
   1.133 -    full_length = flac.FLAC__stream_decoder_get_total_samples(music->flac_decoder);
   1.134 -    if (((music->loop_start >= 0) || (music->loop_end > 0)) &&
   1.135 -        ((music->loop_start < music->loop_end) || (music->loop_end > 0)) &&
   1.136 -         (music->loop_start < full_length) &&
   1.137 -         (music->loop_end <= full_length)) {
   1.138 -        if (music->loop_start < 0) music->loop_start = 0;
   1.139 -        if (music->loop_end == 0) music->loop_end = full_length;
   1.140 +    full_length = (FLAC__int64) flac.FLAC__stream_decoder_get_total_samples(music->flac_decoder);
   1.141 +    if ((music->loop_end > 0) && (music->loop_end <= full_length) &&
   1.142 +        (music->loop_start < music->loop_end)) {
   1.143          music->loop = 1;
   1.144      }
   1.145  
   1.146 @@ -668,7 +668,7 @@
   1.147      FLAC__uint64 seek_sample = (FLAC__uint64) (music->sample_rate * position);
   1.148  
   1.149      SDL_AudioStreamClear(music->stream);
   1.150 -    music->pcm_pos = seek_sample;
   1.151 +    music->pcm_pos = (FLAC__int64) seek_sample;
   1.152      if (!flac.FLAC__stream_decoder_seek_absolute(music->flac_decoder, seek_sample)) {
   1.153          if (flac.FLAC__stream_decoder_get_state(music->flac_decoder) == FLAC__STREAM_DECODER_SEEK_ERROR) {
   1.154              flac.FLAC__stream_decoder_flush(music->flac_decoder);
     2.1 --- a/src/codecs/music_ogg.c	Wed Dec 18 18:55:56 2019 +0300
     2.2 +++ b/src/codecs/music_ogg.c	Thu Dec 19 18:55:02 2019 +0300
     2.3 @@ -230,11 +230,11 @@
     2.4  {
     2.5      char *num_start, *p;
     2.6      ogg_int64_t result = 0;
     2.7 -    char c;
     2.8 +    char c; int val;
     2.9  
    2.10      /* Time is directly expressed as a sample position */
    2.11      if (SDL_strchr(time, ':') == NULL) {
    2.12 -        return (ogg_int64_t)SDL_strtoull(time, NULL, 10);
    2.13 +        return SDL_strtoll(time, NULL, 10);
    2.14      }
    2.15  
    2.16      result = 0;
    2.17 @@ -243,7 +243,9 @@
    2.18      for (p = time; *p != '\0'; ++p) {
    2.19          if (*p == '.' || *p == ':') {
    2.20              c = *p; *p = '\0';
    2.21 -            result = result * 60 + SDL_atoi(num_start);
    2.22 +            if ((val = SDL_atoi(num_start)) < 0)
    2.23 +                return -1;
    2.24 +            result = result * 60 + val;
    2.25              num_start = p + 1;
    2.26              *p = c;
    2.27          }
    2.28 @@ -254,7 +256,8 @@
    2.29          }
    2.30      }
    2.31  
    2.32 -    return (result * 60 + SDL_atoi(num_start)) * samplerate_hz;
    2.33 +    if ((val = SDL_atoi(num_start)) < 0) return -1;
    2.34 +    return (result * 60 + val) * samplerate_hz;
    2.35  }
    2.36  
    2.37  /* Load an OGG stream from an SDL_RWops object */
    2.38 @@ -277,9 +280,6 @@
    2.39      music->volume = MIX_MAX_VOLUME;
    2.40      music->section = -1;
    2.41      music->loop = -1;
    2.42 -    music->loop_start = -1;
    2.43 -    music->loop_end = 0;
    2.44 -    music->loop_len = 0;
    2.45  
    2.46      SDL_zero(callbacks);
    2.47      callbacks.read_func = sdl_read_func;
    2.48 @@ -311,7 +311,6 @@
    2.49  
    2.50          /* Want to match LOOP-START, LOOP_START, etc. Remove - or _ from
    2.51           * string if it is present at position 4. */
    2.52 -
    2.53          if ((argument[4] == '_') || (argument[4] == '-')) {
    2.54              SDL_memmove(argument + 4, argument + 5, SDL_strlen(argument) - 4);
    2.55          }
    2.56 @@ -319,12 +318,19 @@
    2.57          if (SDL_strcasecmp(argument, "LOOPSTART") == 0)
    2.58              music->loop_start = parse_time(value, rate);
    2.59          else if (SDL_strcasecmp(argument, "LOOPLENGTH") == 0) {
    2.60 -            music->loop_len = (ogg_int64_t)SDL_strtoull(value, NULL, 10);
    2.61 +            music->loop_len = SDL_strtoll(value, NULL, 10);
    2.62              is_loop_length = SDL_TRUE;
    2.63          } else if (SDL_strcasecmp(argument, "LOOPEND") == 0) {
    2.64              music->loop_end = parse_time(value, rate);
    2.65              is_loop_length = SDL_FALSE;
    2.66          }
    2.67 +        if (music->loop_start < 0 || music->loop_len < 0 || music->loop_end < 0) {
    2.68 +            music->loop_start = 0;
    2.69 +            music->loop_len = 0;
    2.70 +            music->loop_end = 0;
    2.71 +            SDL_free(param);
    2.72 +            break;  /* ignore tag. */
    2.73 +        }
    2.74          SDL_free(param);
    2.75      }
    2.76  
    2.77 @@ -335,12 +341,8 @@
    2.78      }
    2.79  
    2.80      full_length = vorbis.ov_pcm_total(&music->vf, -1);
    2.81 -    if (((music->loop_start >= 0) || (music->loop_end > 0)) &&
    2.82 -        ((music->loop_start < music->loop_end) || (music->loop_end > 0)) &&
    2.83 -         (music->loop_start < full_length) &&
    2.84 -         (music->loop_end <= full_length)) {
    2.85 -        if (music->loop_start < 0) music->loop_start = 0;
    2.86 -        if (music->loop_end == 0)  music->loop_end = full_length;
    2.87 +    if ((music->loop_end > 0) && (music->loop_end <= full_length) &&
    2.88 +        (music->loop_start < music->loop_end)) {
    2.89          music->loop = 1;
    2.90      }
    2.91  
     3.1 --- a/src/codecs/music_opus.c	Wed Dec 18 18:55:56 2019 +0300
     3.2 +++ b/src/codecs/music_opus.c	Thu Dec 19 18:55:02 2019 +0300
     3.3 @@ -214,11 +214,11 @@
     3.4      const ogg_int64_t samplerate_hz = 48000;
     3.5      char *num_start, *p;
     3.6      ogg_int64_t result = 0;
     3.7 -    char c;
     3.8 +    char c; int val;
     3.9  
    3.10      /* Time is directly expressed as a sample position */
    3.11      if (SDL_strchr(time, ':') == NULL) {
    3.12 -        return (ogg_int64_t)SDL_strtoull(time, NULL, 10);
    3.13 +        return SDL_strtoll(time, NULL, 10);
    3.14      }
    3.15  
    3.16      result = 0;
    3.17 @@ -227,18 +227,22 @@
    3.18      for (p = time; *p != '\0'; ++p) {
    3.19          if (*p == '.' || *p == ':') {
    3.20              c = *p; *p = '\0';
    3.21 -            result = result * 60 + SDL_atoi(num_start);
    3.22 +            if ((val = SDL_atoi(num_start)) < 0)
    3.23 +                return -1;
    3.24 +            result = result * 60 + val;
    3.25              num_start = p + 1;
    3.26              *p = c;
    3.27          }
    3.28  
    3.29          if (*p == '.') {
    3.30 -            return result * samplerate_hz
    3.31 -                + (ogg_int64_t) (SDL_atof(p) * samplerate_hz);
    3.32 +            double val_f = SDL_atof(p);
    3.33 +            if (val_f < 0) return -1;
    3.34 +            return result * samplerate_hz + (ogg_int64_t) (val_f * samplerate_hz);
    3.35          }
    3.36      }
    3.37  
    3.38 -    return (result * 60 + SDL_atoi(num_start)) * samplerate_hz;
    3.39 +    if ((val = SDL_atoi(num_start)) < 0) return -1;
    3.40 +    return (result * 60 + val) * samplerate_hz;
    3.41  }
    3.42  
    3.43  static SDL_bool is_loop_tag(const char *tag)
    3.44 @@ -267,9 +271,6 @@
    3.45      music->volume = MIX_MAX_VOLUME;
    3.46      music->section = -1;
    3.47      music->loop = -1;
    3.48 -    music->loop_start = -1;
    3.49 -    music->loop_end = 0;
    3.50 -    music->loop_len = 0;
    3.51  
    3.52      SDL_zero(callbacks);
    3.53      callbacks.read = sdl_read_func;
    3.54 @@ -315,12 +316,19 @@
    3.55          if (SDL_strcasecmp(argument, "LOOPSTART") == 0)
    3.56              music->loop_start = parse_time(value);
    3.57          else if (SDL_strcasecmp(argument, "LOOPLENGTH") == 0) {
    3.58 -            music->loop_len = (ogg_int64_t)SDL_strtoull(value, NULL, 10);
    3.59 +            music->loop_len = SDL_strtoll(value, NULL, 10);
    3.60              is_loop_length = SDL_TRUE;
    3.61          } else if (SDL_strcasecmp(argument, "LOOPEND") == 0) {
    3.62              music->loop_end = parse_time(value);
    3.63              is_loop_length = SDL_FALSE;
    3.64          }
    3.65 +        if (music->loop_start < 0 || music->loop_len < 0 || music->loop_end < 0) {
    3.66 +            music->loop_start = 0;
    3.67 +            music->loop_len = 0;
    3.68 +            music->loop_end = 0;
    3.69 +            SDL_free(param);
    3.70 +            break;  /* ignore tag. */
    3.71 +        }
    3.72          SDL_free(param);
    3.73      }
    3.74  
    3.75 @@ -331,12 +339,8 @@
    3.76      }
    3.77  
    3.78      full_length = opus.op_pcm_total(music->of, -1);
    3.79 -    if (((music->loop_start >= 0) || (music->loop_end > 0)) &&
    3.80 -        ((music->loop_start < music->loop_end) || (music->loop_end > 0)) &&
    3.81 -         (music->loop_start < full_length) &&
    3.82 -         (music->loop_end <= full_length)) {
    3.83 -        if (music->loop_start < 0) music->loop_start = 0;
    3.84 -        if (music->loop_end == 0)  music->loop_end = full_length;
    3.85 +    if ((music->loop_end > 0) && (music->loop_end <= full_length) &&
    3.86 +        (music->loop_start < music->loop_end)) {
    3.87          music->loop = 1;
    3.88      }
    3.89