diff mbox

[FFmpeg-devel] pnmdec: make sure v is capped by maxval

Message ID 7fb0049c-c650-9f1a-bf9d-77b5d40e61af@googlemail.com
State Accepted
Headers show

Commit Message

Andreas Cadhalpun Nov. 10, 2016, 7:52 p.m. UTC
On 10.11.2016 02:26, Michael Niedermayer wrote:
> On Wed, Nov 09, 2016 at 10:46:03PM +0100, Andreas Cadhalpun wrote:
>>  pnmdec.c |    4 ++++
>>  1 file changed, 4 insertions(+)
>> a970cb981be02ea692d0bf2e68976077f14f2de3  0001-pnmdec-make-sure-v-is-capped-by-maxval.patch
>> From f315a3cfe35377a2638dc2294200a288408dc784 Mon Sep 17 00:00:00 2001
>> From: Andreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>
>> Date: Wed, 9 Nov 2016 01:09:35 +0100
>> Subject: [PATCH] pnmdec: make sure v is capped by maxval
>>
>> Otherwise put_bits can be called with a value that doesn't fit in the
>> sample_len, causing an assertion failure.
>> ---
>>  libavcodec/pnmdec.c | 4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/libavcodec/pnmdec.c b/libavcodec/pnmdec.c
>> index ca97cc3..0f6a895 100644
>> --- a/libavcodec/pnmdec.c
>> +++ b/libavcodec/pnmdec.c
>> @@ -144,6 +144,10 @@ static int pnm_decode_frame(AVCodecContext *avctx, void *data,
>>                      } else {
>>                          /* read a sequence of digits */
>>                          do {
>> +                            if (v > (INT_MAX - c) / 10 || 10 * v + c > s->maxval) {
>> +                                av_log(avctx, AV_LOG_ERROR, "value 10 * %d + %d larger than maxval %d\n", v, c, s->maxval);
>> +                                return AVERROR_INVALIDDATA;
>> +                            }
> 
> this test should nt be inside the loop
> you can try to benchmark with START/STOP_TIMER to see what effect
> this has (i didnt try but i expect it to be bad), this is the
> innermost loop of the decoder
> 
> you can just unroll the loop by 5, thats the max number of iterations
> i think, which avoids the overflow
> it also should make the code faster

Done, new patch attached.

> iam reading in man ppm and others:
> "The maximum color value (Maxval), again in ASCII decimal.  Must be less than 65536"

Indeed, I'll send a separate match limiting maxval.

Best regards,
Andreas

Comments

Michael Niedermayer Nov. 11, 2016, 1:03 a.m. UTC | #1
On Thu, Nov 10, 2016 at 08:52:29PM +0100, Andreas Cadhalpun wrote:
> On 10.11.2016 02:26, Michael Niedermayer wrote:
> > On Wed, Nov 09, 2016 at 10:46:03PM +0100, Andreas Cadhalpun wrote:
> >>  pnmdec.c |    4 ++++
> >>  1 file changed, 4 insertions(+)
> >> a970cb981be02ea692d0bf2e68976077f14f2de3  0001-pnmdec-make-sure-v-is-capped-by-maxval.patch
> >> From f315a3cfe35377a2638dc2294200a288408dc784 Mon Sep 17 00:00:00 2001
> >> From: Andreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>
> >> Date: Wed, 9 Nov 2016 01:09:35 +0100
> >> Subject: [PATCH] pnmdec: make sure v is capped by maxval
> >>
> >> Otherwise put_bits can be called with a value that doesn't fit in the
> >> sample_len, causing an assertion failure.
> >> ---
> >>  libavcodec/pnmdec.c | 4 ++++
> >>  1 file changed, 4 insertions(+)
> >>
> >> diff --git a/libavcodec/pnmdec.c b/libavcodec/pnmdec.c
> >> index ca97cc3..0f6a895 100644
> >> --- a/libavcodec/pnmdec.c
> >> +++ b/libavcodec/pnmdec.c
> >> @@ -144,6 +144,10 @@ static int pnm_decode_frame(AVCodecContext *avctx, void *data,
> >>                      } else {
> >>                          /* read a sequence of digits */
> >>                          do {
> >> +                            if (v > (INT_MAX - c) / 10 || 10 * v + c > s->maxval) {
> >> +                                av_log(avctx, AV_LOG_ERROR, "value 10 * %d + %d larger than maxval %d\n", v, c, s->maxval);
> >> +                                return AVERROR_INVALIDDATA;
> >> +                            }
> > 
> > this test should nt be inside the loop
> > you can try to benchmark with START/STOP_TIMER to see what effect
> > this has (i didnt try but i expect it to be bad), this is the
> > innermost loop of the decoder
> > 
> > you can just unroll the loop by 5, thats the max number of iterations
> > i think, which avoids the overflow
> > it also should make the code faster
> 
> Done, new patch attached.
> 
> > iam reading in man ppm and others:
> > "The maximum color value (Maxval), again in ASCII decimal.  Must be less than 65536"
> 
> Indeed, I'll send a separate match limiting maxval.
> 
> Best regards,
> Andreas
> 

>  pnmdec.c |   10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 0dd61abddc422dd2ac37356f8271822d7e801b8e  0001-pnmdec-make-sure-v-is-capped-by-maxval.patch
> From 2d402d8a38223b8c3c58d3e71e734932c9bdadae Mon Sep 17 00:00:00 2001
> From: Andreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>
> Date: Wed, 9 Nov 2016 01:09:35 +0100
> Subject: [PATCH] pnmdec: make sure v is capped by maxval
> 
> Otherwise put_bits can be called with a value that doesn't fit in the
> sample_len, causing an assertion failure.

LGTM

thx

[...]
Andreas Cadhalpun Nov. 12, 2016, 12:40 a.m. UTC | #2
On 11.11.2016 02:03, Michael Niedermayer wrote:
> On Thu, Nov 10, 2016 at 08:52:29PM +0100, Andreas Cadhalpun wrote:
>>  pnmdec.c |   10 +++++++---
>>  1 file changed, 7 insertions(+), 3 deletions(-)
>> 0dd61abddc422dd2ac37356f8271822d7e801b8e  0001-pnmdec-make-sure-v-is-capped-by-maxval.patch
>> From 2d402d8a38223b8c3c58d3e71e734932c9bdadae Mon Sep 17 00:00:00 2001
>> From: Andreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>
>> Date: Wed, 9 Nov 2016 01:09:35 +0100
>> Subject: [PATCH] pnmdec: make sure v is capped by maxval
>>
>> Otherwise put_bits can be called with a value that doesn't fit in the
>> sample_len, causing an assertion failure.
> 
> LGTM

Pushed.

Best regards,
Andreas
diff mbox

Patch

From 2d402d8a38223b8c3c58d3e71e734932c9bdadae Mon Sep 17 00:00:00 2001
From: Andreas Cadhalpun <Andreas.Cadhalpun@googlemail.com>
Date: Wed, 9 Nov 2016 01:09:35 +0100
Subject: [PATCH] pnmdec: make sure v is capped by maxval

Otherwise put_bits can be called with a value that doesn't fit in the
sample_len, causing an assertion failure.
---
 libavcodec/pnmdec.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/libavcodec/pnmdec.c b/libavcodec/pnmdec.c
index ca97cc3..958c5e4 100644
--- a/libavcodec/pnmdec.c
+++ b/libavcodec/pnmdec.c
@@ -43,7 +43,7 @@  static int pnm_decode_frame(AVCodecContext *avctx, void *data,
     int buf_size         = avpkt->size;
     PNMContext * const s = avctx->priv_data;
     AVFrame * const p    = data;
-    int i, j, n, linesize, h, upgrade = 0, is_mono = 0;
+    int i, j, k, n, linesize, h, upgrade = 0, is_mono = 0;
     unsigned char *ptr;
     int components, sample_len, ret;
 
@@ -143,10 +143,14 @@  static int pnm_decode_frame(AVCodecContext *avctx, void *data,
                         v = (*s->bytestream++)&1;
                     } else {
                         /* read a sequence of digits */
-                        do {
+                        for (k = 0; k < 5 && c <= 9; k += 1) {
                             v = 10*v + c;
                             c = (*s->bytestream++) - '0';
-                        } while (c <= 9);
+                        }
+                        if (v > s->maxval) {
+                            av_log(avctx, AV_LOG_ERROR, "value %d larger than maxval %d\n", v, s->maxval);
+                            return AVERROR_INVALIDDATA;
+                        }
                     }
                     if (sample_len == 16) {
                         ((uint16_t*)ptr)[j] = (((1<<sample_len)-1)*v + (s->maxval>>1))/s->maxval;
-- 
2.10.2