|
|
Chromium Code Reviews|
Created:
4 years, 8 months ago by servolk Modified:
4 years, 8 months ago CC:
chromium-reviews, posciak+watch_chromium.org, jam, mcasas+watch_chromium.org, feature-media-reviews_chromium.org, darin-cc_chromium.org, piman+watch_chromium.org Base URL:
https://chromium.googlesource.com/chromium/src.git@master Target Ref:
refs/pending/heads/master Project:
chromium Visibility:
Public. |
DescriptionCheck frame coded size in H264 parsers to avoid integer overflows
The bug crbug.com/541669 was originally found by fuzzing and reported
for media/formats/mp2t/es_parser_h264.cc, but I've noticed that
content/common/gpu/media/h264_decoder.cc potentially has the same
issue.
BUG=541669
Committed: https://crrev.com/eed4015f99aedcc6a989ffc43869c324bc5d3c1b
Cr-Commit-Position: refs/heads/master@{#388808}
Patch Set 1 #
Total comments: 4
Messages
Total messages: 26 (9 generated)
Description was changed from ========== Check frame coded size in H264 parsers to avoid integer overflows The bug crbug.com/541669 was originally found by fuzzing and reported for media/formats/mp2t/es_parser_h264.cc, but I've noticed that content/common/gpu/media/h264_decoder.cc potentially has the same issue. BUG=541669 ========== to ========== Check frame coded size in H264 parsers to avoid integer overflows The bug crbug.com/541669 was originally found by fuzzing and reported for media/formats/mp2t/es_parser_h264.cc, but I've noticed that content/common/gpu/media/h264_decoder.cc potentially has the same issue. BUG=541669 ==========
servolk@chromium.org changed reviewers: + posciak@chromium.org, watk@chromium.org
Nice, lgtm
On 2016/04/15 20:01:59, watk wrote: > Nice, lgtm Ping. posciak@ could you take a look at content/common/gpu/media/h264_decoder.cc please?
https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... File content/common/gpu/media/h264_decoder.cc (right): https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... content/common/gpu/media/h264_decoder.cc:1089: if (width_mb > std::numeric_limits<int>::max() / 16 || Could we perhaps use: base::IsValueInRangeForNumericType<int>(width_mb * 16) ?
https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... File content/common/gpu/media/h264_decoder.cc (right): https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... content/common/gpu/media/h264_decoder.cc:1089: if (width_mb > std::numeric_limits<int>::max() / 16 || On 2016/04/20 04:22:09, Pawel Osciak wrote: > Could we perhaps use: > base::IsValueInRangeForNumericType<int>(width_mb * 16) ? Well, we are actually trying to avoid integer overflow when multiplying width_mb by 16. So correct me if I'm missing something, but I think your suggested code would do multiplication first (with potential integer overflow, since boths multiplicands are ints), then would pass the multiplication result into IsValueInRangeForNumericType, which would always be in range, since the overflow has already happened. We could probably add an explicit widening cast on width_mb before attempting multiplication, but that would result in uglier (IMHO) code. I believe base::IsValueInRangeForNumericType is mostly useful in situations where you are about to make a narrowing cast and want to ensure that it's safe. This is not that situation. Besides, I believe that dividing by 16 is optimized into a simple bit shift by any decent modern compiler, so the performance shouldn't be an issue here.
https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... File content/common/gpu/media/h264_decoder.cc (right): https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... content/common/gpu/media/h264_decoder.cc:1089: if (width_mb > std::numeric_limits<int>::max() / 16 || On 2016/04/20 17:32:53, servolk wrote: > On 2016/04/20 04:22:09, Pawel Osciak wrote: > > Could we perhaps use: > > base::IsValueInRangeForNumericType<int>(width_mb * 16) ? > > Well, we are actually trying to avoid integer overflow when multiplying width_mb > by 16. So correct me if I'm missing something, but I think your suggested code > would do multiplication first (with potential integer overflow, since boths > multiplicands are ints), then would pass the multiplication result into > IsValueInRangeForNumericType, which would always be in range, since the overflow > has already happened. Yes, unless the result was of a larger type: int a = INT_MAX; uint64_t b = a * 16; will not result in an overflow. I thought that was how this template worked. In any case, saying something like: base::IsValueInRangeForNumericType<int>(width_mb * 16u) should be enough.
https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... File content/common/gpu/media/h264_decoder.cc (right): https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... content/common/gpu/media/h264_decoder.cc:1089: if (width_mb > std::numeric_limits<int>::max() / 16 || On 2016/04/21 01:03:53, Pawel Osciak wrote: > On 2016/04/20 17:32:53, servolk wrote: > > On 2016/04/20 04:22:09, Pawel Osciak wrote: > > > Could we perhaps use: > > > base::IsValueInRangeForNumericType<int>(width_mb * 16) ? > > > > Well, we are actually trying to avoid integer overflow when multiplying > width_mb > > by 16. So correct me if I'm missing something, but I think your suggested code > > would do multiplication first (with potential integer overflow, since boths > > multiplicands are ints), then would pass the multiplication result into > > IsValueInRangeForNumericType, which would always be in range, since the > overflow > > has already happened. > > Yes, unless the result was of a larger type: > int a = INT_MAX; uint64_t b = a * 16; will not result in an overflow. I thought > that was how this template worked. In any case, saying something like: > base::IsValueInRangeForNumericType<int>(width_mb * 16u) should be enough. First of all, you probably meant 16ull, as 16u is still the same bitness as int, just unsigned. I understand that we could work around this by explicitly widening one of the arguments (or both). But to be honest, I don't understand why it would be any better than the current code. Why would we resort to doing 128-bit multiplication (on 64-bit platforms), when we could achieve the same goal with 64-bit arithmetic with the current code? How is it any better than dividing by 16, which is going to be a simple bitshift?
On 2016/04/21 01:24:06, servolk wrote: > https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... > File content/common/gpu/media/h264_decoder.cc (right): > > https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... > content/common/gpu/media/h264_decoder.cc:1089: if (width_mb > > std::numeric_limits<int>::max() / 16 || > On 2016/04/21 01:03:53, Pawel Osciak wrote: > > On 2016/04/20 17:32:53, servolk wrote: > > > On 2016/04/20 04:22:09, Pawel Osciak wrote: > > > > Could we perhaps use: > > > > base::IsValueInRangeForNumericType<int>(width_mb * 16) ? > > > > > > Well, we are actually trying to avoid integer overflow when multiplying > > width_mb > > > by 16. So correct me if I'm missing something, but I think your suggested > code > > > would do multiplication first (with potential integer overflow, since boths > > > multiplicands are ints), then would pass the multiplication result into > > > IsValueInRangeForNumericType, which would always be in range, since the > > overflow > > > has already happened. > > > > Yes, unless the result was of a larger type: > > int a = INT_MAX; uint64_t b = a * 16; will not result in an overflow. I > thought > > that was how this template worked. In any case, saying something like: > > base::IsValueInRangeForNumericType<int>(width_mb * 16u) should be enough. > > First of all, you probably meant 16ull, as 16u is still the same bitness as int, > just unsigned. Sorry, I actually did mean 16u, because that makes it one bit larger, as there is no sign bit :) int a = INT_MAX; base::IsValueInRangeForNumericType<int>(a * 16) == true base::IsValueInRangeForNumericType<int>(a * 16u) == false
On 2016/04/21 01:33:11, Pawel Osciak wrote: > On 2016/04/21 01:24:06, servolk wrote: > > > https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... > > File content/common/gpu/media/h264_decoder.cc (right): > > > > > https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... > > content/common/gpu/media/h264_decoder.cc:1089: if (width_mb > > > std::numeric_limits<int>::max() / 16 || > > On 2016/04/21 01:03:53, Pawel Osciak wrote: > > > On 2016/04/20 17:32:53, servolk wrote: > > > > On 2016/04/20 04:22:09, Pawel Osciak wrote: > > > > > Could we perhaps use: > > > > > base::IsValueInRangeForNumericType<int>(width_mb * 16) ? > > > > > > > > Well, we are actually trying to avoid integer overflow when multiplying > > > width_mb > > > > by 16. So correct me if I'm missing something, but I think your suggested > > code > > > > would do multiplication first (with potential integer overflow, since > boths > > > > multiplicands are ints), then would pass the multiplication result into > > > > IsValueInRangeForNumericType, which would always be in range, since the > > > overflow > > > > has already happened. > > > > > > Yes, unless the result was of a larger type: > > > int a = INT_MAX; uint64_t b = a * 16; will not result in an overflow. I > > thought > > > that was how this template worked. In any case, saying something like: > > > base::IsValueInRangeForNumericType<int>(width_mb * 16u) should be enough. > > > > First of all, you probably meant 16ull, as 16u is still the same bitness as > int, > > just unsigned. > > Sorry, I actually did mean 16u, because that makes it one bit larger, as there > is no sign bit :) > > int a = INT_MAX; > base::IsValueInRangeForNumericType<int>(a * 16) == true > base::IsValueInRangeForNumericType<int>(a * 16u) == false That said, I don't disagree with your arguments, I'm not particularly opposed to the current version. Please choose whichever variant you'd prefer, lgtm for the current version as well. Thanks for the fix!
On 2016/04/21 01:41:25, Pawel Osciak wrote: > On 2016/04/21 01:33:11, Pawel Osciak wrote: > > On 2016/04/21 01:24:06, servolk wrote: > > > > > > https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... > > > File content/common/gpu/media/h264_decoder.cc (right): > > > > > > > > > https://codereview.chromium.org/1896533002/diff/1/content/common/gpu/media/h2... > > > content/common/gpu/media/h264_decoder.cc:1089: if (width_mb > > > > std::numeric_limits<int>::max() / 16 || > > > On 2016/04/21 01:03:53, Pawel Osciak wrote: > > > > On 2016/04/20 17:32:53, servolk wrote: > > > > > On 2016/04/20 04:22:09, Pawel Osciak wrote: > > > > > > Could we perhaps use: > > > > > > base::IsValueInRangeForNumericType<int>(width_mb * 16) ? > > > > > > > > > > Well, we are actually trying to avoid integer overflow when multiplying > > > > width_mb > > > > > by 16. So correct me if I'm missing something, but I think your > suggested > > > code > > > > > would do multiplication first (with potential integer overflow, since > > boths > > > > > multiplicands are ints), then would pass the multiplication result into > > > > > IsValueInRangeForNumericType, which would always be in range, since the > > > > overflow > > > > > has already happened. > > > > > > > > Yes, unless the result was of a larger type: > > > > int a = INT_MAX; uint64_t b = a * 16; will not result in an overflow. I > > > thought > > > > that was how this template worked. In any case, saying something like: > > > > base::IsValueInRangeForNumericType<int>(width_mb * 16u) should be enough. > > > > > > First of all, you probably meant 16ull, as 16u is still the same bitness as > > int, > > > just unsigned. > > > > Sorry, I actually did mean 16u, because that makes it one bit larger, as there > > is no sign bit :) > > > > int a = INT_MAX; > > base::IsValueInRangeForNumericType<int>(a * 16) == true > > base::IsValueInRangeForNumericType<int>(a * 16u) == false > > That said, I don't disagree with your arguments, I'm not particularly opposed to > the current version. Please choose whichever variant you'd prefer, lgtm for the > current version as well. Thanks for the fix! Unfortunately 16u still doesn't work. Yes, it happens to give the right result for INT_MAX. But here is a counter example (let's consider 32-bit for simplicity). Imagine we got width_mb = 0x77FF FFFF. Then width_mb * 16u == 0x0007 7FFF FFF0, but in 32-bit unsigned arithmetic it becomes just 0x7FFF FFF0 due to overflow, which is less than INT_MAX == 0x7FFF FFFF! So base::IsValueInRangeForNumericType<int>(width_mb * 16u) would return true for width_mb==0x77FF FFFF, which is wrong here. I believe the current code is much simpler and does the job correctly. So I'll land it as it is. Thanks for the review!
The CQ bit was checked by servolk@chromium.org
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1896533002/1 View timeline at https://chromium-cq-status.appspot.com/patch-timeline/1896533002/1
The CQ bit was unchecked by commit-bot@chromium.org
Try jobs failed on following builders: linux_chromium_chromeos_rel_ng on tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/linux_chromium_...)
The CQ bit was checked by servolk@chromium.org
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1896533002/1 View timeline at https://chromium-cq-status.appspot.com/patch-timeline/1896533002/1
The CQ bit was unchecked by commit-bot@chromium.org
Try jobs failed on following builders: linux_chromium_chromeos_rel_ng on tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/linux_chromium_...)
The CQ bit was checked by servolk@chromium.org
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1896533002/1 View timeline at https://chromium-cq-status.appspot.com/patch-timeline/1896533002/1
Message was sent while issue was closed.
Description was changed from ========== Check frame coded size in H264 parsers to avoid integer overflows The bug crbug.com/541669 was originally found by fuzzing and reported for media/formats/mp2t/es_parser_h264.cc, but I've noticed that content/common/gpu/media/h264_decoder.cc potentially has the same issue. BUG=541669 ========== to ========== Check frame coded size in H264 parsers to avoid integer overflows The bug crbug.com/541669 was originally found by fuzzing and reported for media/formats/mp2t/es_parser_h264.cc, but I've noticed that content/common/gpu/media/h264_decoder.cc potentially has the same issue. BUG=541669 ==========
Message was sent while issue was closed.
Committed patchset #1 (id:1)
Message was sent while issue was closed.
Description was changed from ========== Check frame coded size in H264 parsers to avoid integer overflows The bug crbug.com/541669 was originally found by fuzzing and reported for media/formats/mp2t/es_parser_h264.cc, but I've noticed that content/common/gpu/media/h264_decoder.cc potentially has the same issue. BUG=541669 ========== to ========== Check frame coded size in H264 parsers to avoid integer overflows The bug crbug.com/541669 was originally found by fuzzing and reported for media/formats/mp2t/es_parser_h264.cc, but I've noticed that content/common/gpu/media/h264_decoder.cc potentially has the same issue. BUG=541669 Committed: https://crrev.com/eed4015f99aedcc6a989ffc43869c324bc5d3c1b Cr-Commit-Position: refs/heads/master@{#388808} ==========
Message was sent while issue was closed.
Patchset 1 (id:??) landed as https://crrev.com/eed4015f99aedcc6a989ffc43869c324bc5d3c1b Cr-Commit-Position: refs/heads/master@{#388808} |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
