digitalmars.D - The case for integer overflow checks?
- Guillaume Piolat (28/28) Sep 15 2017 As a die-hard native programmer I was always disgusted by integer
- Kagamin (11/13) Sep 15 2017 Do you hope to see such code? Since width can't be negative, C
- Guillaume Piolat (10/20) Sep 15 2017 This code isn't to be taken literally, the important bit is that
- Kagamin (9/15) Sep 15 2017 As long as it works in bounds it should be more or less ok.
- Guillaume Piolat (5/9) Sep 15 2017 Point taken about proper allocator with returned size. It's
- Walter Bright (7/10) Sep 16 2017 The problem with C is that it isn't mechanically checkable. There's no w...
- Walter Bright (8/11) Sep 16 2017 The Equifax disaster is another lesson the airframe industry learned gen...
- Adam D. Ruppe (3/5) Sep 15 2017 That's often a big mistake. Lots of people do it... but you
- Neia Neutuladh (14/19) Sep 15 2017 Signed integers have the same issue, no? Using int32s:
- Guillaume Piolat (5/9) Sep 15 2017 It's true that my example doesn't fail in the same way if eg.
- Walter Bright (2/4) Sep 15 2017 https://dlang.org/phobos/std_experimental_checkedint.html
- bitwise (2/7) Sep 15 2017 Will this ever be integrated directly into the compiler?
- Walter Bright (2/6) Sep 15 2017 No plans to do so.
- Jonathan M Davis (10/16) Sep 18 2017 There also really isn't a need to do so. If you care about having the
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/5) Sep 18 2017 If there was no need then C/C++ compilers wouldn't provide it as
- Kagamin (3/5) Sep 18 2017 Do they check unsigned integers?
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (3/4) Sep 18 2017 No, I don't believe they do, as unsigned integers are modular in
- Kagamin (6/8) Sep 20 2017 So you can't check third party code because it pervasively uses
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (5/13) Sep 20 2017 For more complex third party code you have to vet it anyway for
- Jonathan M Davis (6/11) Sep 18 2017 We have std.experimental.checkedint, so why would there be any need for ...
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (4/8) Sep 18 2017 So that you can use third party libraries?
- Guillaume Piolat (10/15) Sep 18 2017 On Monday, 18 September 2017 at 08:27:21 UTC, Jonathan M Davis
- Andrei Alexandrescu (6/23) Sep 18 2017 For the record, with the help of std.experimental.checkedint, the change...
- Dennis Cote (5/11) Sep 18 2017 Can it do something other than abort? Can it throw an overflow
- Moritz Maxeiner (8/20) Sep 18 2017 Yes. Use one of the provided hooks (e.g. [1][2][3]) or write one
- Jonathan M Davis (6/28) Sep 18 2017 Yeah, it's really quite flexible with minimal code. Andrei talked about ...
As a die-hard native programmer I was always disgusted by integer overflow checks and array bounds checks. Littering code with branches everywhere? Just let me go as fast possible please! Last week I was explained by security people how a part of vulnerabilities todays are attacks on image parsers, and how integer overflow checks may help there. IIRC a typical attack on image format parser is to forge an image with a width and height that will overflow an int. On allocation, the result of the multiplied wraps around like this: int width = parse_width_from_stream(); // eg: 131072 int height = parse_height_from_stream(); // eg: 131073 ubyte[] data = malloc(width * height * 4); // wraps around, allocates way less memory than that This prepare the program to access data that is outside the truly allocated area, for example in another block. The other part of the job is to actually jump in the injected code, but I've not understood this part (somehow implied knowing how the specific allocator work in this case). Somehow integer overflows are part of sophisticated attacks for which it's a building block. If overflow checks happen to be more or less cheap like (surprinsingly) array bounds checks are, it could be a nice thing to pay for. References: - Integer Overflow into Information Disclosure http://nullprogram.com/blog/2017/07/19/ - Basic Integer Overflows http://phrack.org/issues/60/10.html
Sep 15 2017
On Friday, 15 September 2017 at 08:46:57 UTC, Guillaume Piolat wrote:int width = parse_width_from_stream(); // eg: 131072 int height = parse_height_from_stream(); // eg: 131073Do you hope to see such code? Since width can't be negative, C programmer would use unsigned integer for it, and you can't prohibit overflow for unsigned integer. It is unfixable for array length, because unsigned integers are invariably used for length. Blueborn vulnerabilities rely on overflow of unsigned integers (for buffer length) to trigger buffer overflow in calls to memcopy. But buffer overflow would normally be prevented by bound checks in case of integer overflow. Just have a safer wrapper around malloc in your example.
Sep 15 2017
On Friday, 15 September 2017 at 12:04:27 UTC, Kagamin wrote:Do you hope to see such code? Since width can't be negative, C programmer would use unsigned integer for it, and you can't prohibit overflow for unsigned integer. It is unfixable for array length, because unsigned integers are invariably used for length. Blueborn vulnerabilities rely on overflow of unsigned integers (for buffer length) to trigger buffer overflow in calls to memcopy.This code isn't to be taken literally, the important bit is that silent integer overflow allows this kind of attacks.But buffer overflow would normally be prevented by bound checks in case of integer overflow.Well here I don't think so: this attack is used to adress a very large space, while having a very small actually allocated memory space. Bounds would be too large to matter.have a safer wrapper around malloc in your example.That would be calloc. The point is that it's easy to make the vulnerability disappear, once you know about such things and traps. It falls under the "unknown unknowns" category of risk most of the time though.
Sep 15 2017
On Friday, 15 September 2017 at 12:25:10 UTC, Guillaume Piolat wrote:Well here I don't think so: this attack is used to adress a very large space, while having a very small actually allocated memory space. Bounds would be too large to matter.As long as it works in bounds it should be more or less ok.That would be calloc.I mean allocator that returns bound checked array. And you can call calloc incorrectly too.The point is that it's easy to make the vulnerability disappear, once you know about such things and traps.It's not because nobody knows about buffer overflows. C leaves the task on the programmer, and the task is too huge for manual labor without help from the language, ecosystem and coding practices, of course nobody does it.
Sep 15 2017
Point taken about proper allocator with returned size. It's indeed a minority of cases in regular D. On Friday, 15 September 2017 at 16:39:46 UTC, Kagamin wrote:It's not because nobody knows about buffer overflows. C leaves the task on the programmer, and the task is too huge for manual labor without help from the language, ecosystem and coding practices, of course nobody does it.I was wondering because some image libraries do use malloc(), for the decreased memory usage and possibility of false positives.
Sep 15 2017
On 9/15/2017 9:39 AM, Kagamin wrote:It's not because nobody knows about buffer overflows. C leaves the task on the programmer, and the task is too huge for manual labor without help from the language, ecosystem and coding practices, of course nobody does it.The problem with C is that it isn't mechanically checkable. There's no way to reliably tell if a piece of code is memory safe or not, regardless of how competent the programmer is or how hard he works. The programming community is coming around, very slowly, to what the airframe industry learned generations ago. I.e. you *never* rely on people in the system not making mistakes.
Sep 16 2017
On 9/16/2017 2:55 AM, Walter Bright wrote:The programming community is coming around, very slowly, to what the airframe industry learned generations ago. I.e. you *never* rely on people in the system not making mistakes.The Equifax disaster is another lesson the airframe industry learned generations ago. Compartmentalization. (Battleships and spy networks learned that centuries ago.) A single security error in the Equifax system led to losing ALL of their data. Sensitive data should be compartmentalized, i.e. being spread among systems each with their own security. Access to one compartment does not give access to any other compartments.
Sep 16 2017
On Friday, 15 September 2017 at 12:04:27 UTC, Kagamin wrote:Since width can't be negative, C programmer would use unsigned integer for itThat's often a big mistake. Lots of people do it... but you shouldn't, exactly because of the wraparound behavior.
Sep 15 2017
On Friday, 15 September 2017 at 12:33:56 UTC, Adam D. Ruppe wrote:On Friday, 15 September 2017 at 12:04:27 UTC, Kagamin wrote:Signed integers have the same issue, no? Using int32s: 2147483635 * 400000000 * 4 = 674836480 It's just that you're more likely to be able to detect it, since a lot of inputs result in negative numbers. One solution is to switch to the next larger integer size. That works up to 32-bit numbers. When you hit 64-bit, you've got to switch to BigInt. Another solution is to check the overflow bit as appropriate. The checkedint package automates that. The last solution that I can think of, specific to this type of thing, is to use the result to allocate a bounds-checked array, where the allocation function yields the appropriately sized array. You'll get an array bounds error that may be inscrutable.Since width can't be negative, C programmer would use unsigned integer for itThat's often a big mistake. Lots of people do it... but you shouldn't, exactly because of the wraparound behavior.
Sep 15 2017
On Friday, 15 September 2017 at 16:04:08 UTC, Neia Neutuladh wrote:The last solution that I can think of, specific to this type of thing, is to use the result to allocate a bounds-checked array, where the allocation function yields the appropriately sized array. You'll get an array bounds error that may be inscrutable.It's true that my example doesn't fail in the same way if eg. new ubyte[width * height] was used.
Sep 15 2017
On 9/15/2017 1:46 AM, Guillaume Piolat wrote:If overflow checks happen to be more or less cheap like (surprinsingly) array bounds checks are, it could be a nice thing to pay for.https://dlang.org/phobos/std_experimental_checkedint.html
Sep 15 2017
On Friday, 15 September 2017 at 21:21:01 UTC, Walter Bright wrote:On 9/15/2017 1:46 AM, Guillaume Piolat wrote:Will this ever be integrated directly into the compiler?If overflow checks happen to be more or less cheap like (surprinsingly) array bounds checks are, it could be a nice thing to pay for.https://dlang.org/phobos/std_experimental_checkedint.html
Sep 15 2017
On 9/15/2017 5:00 PM, bitwise wrote:On Friday, 15 September 2017 at 21:21:01 UTC, Walter Bright wrote:No plans to do so.https://dlang.org/phobos/std_experimental_checkedint.htmlWill this ever be integrated directly into the compiler?
Sep 15 2017
On Friday, September 15, 2017 19:01:18 Walter Bright via Digitalmars-d wrote:On 9/15/2017 5:00 PM, bitwise wrote:There also really isn't a need to do so. If you care about having the overflow checks, then you use Checked. If you don't, you don't. And from what I recall of Andrei's talk on it, Checked is insanely customizable - which a built-in feature wouldn't be. Personally, I've never had a need for checked ints. I've rarely seen code that would care, and when you do, it's usually pretty easy to deal with it properly. But Checked is there for those who feel the need. - Jonathan M DavisOn Friday, 15 September 2017 at 21:21:01 UTC, Walter Bright wrote:No plans to do so.https://dlang.org/phobos/std_experimental_checkedint.htmlWill this ever be integrated directly into the compiler?
Sep 18 2017
On Monday, 18 September 2017 at 08:27:21 UTC, Jonathan M Davis wrote:There also really isn't a need to do so.If there was no need then C/C++ compilers wouldn't provide it as an option…
Sep 18 2017
On Monday, 18 September 2017 at 08:35:44 UTC, Ola Fosheim Grøstad wrote:If there was no need then C/C++ compilers wouldn't provide it as an option…Do they check unsigned integers?
Sep 18 2017
On Monday, 18 September 2017 at 11:42:19 UTC, Kagamin wrote:Do they check unsigned integers?No, I don't believe they do, as unsigned integers are modular in C/C++. (And in D also signed integers are modular).
Sep 18 2017
On Monday, 18 September 2017 at 17:46:52 UTC, Ola Fosheim Grøstad wrote:No, I don't believe they do, as unsigned integers are modular in C/C++.So you can't check third party code because it pervasively uses unsigned integers for lengths, sizes and everything else, obvious example: https://fossies.org/dox/libpng-1.6.32/structpng__info__def.html
Sep 20 2017
On Wednesday, 20 September 2017 at 10:01:14 UTC, Kagamin wrote:On Monday, 18 September 2017 at 17:46:52 UTC, Ola Fosheim Grøstad wrote:For more complex third party code you have to vet it anyway for bad practices. For utilitarian libraries it could be quite useful. So, it all depends.No, I don't believe they do, as unsigned integers are modular in C/C++.So you can't check third party code because it pervasively uses unsigned integers for lengths, sizes and everything else, obvious example: https://fossies.org/dox/libpng-1.6.32/structpng__info__def.html
Sep 20 2017
On Monday, September 18, 2017 08:35:44 Ola Fosheim Grøstad via Digitalmars-d wrote:On Monday, 18 September 2017 at 08:27:21 UTC, Jonathan M Davis wrote:We have std.experimental.checkedint, so why would there be any need for it to be in the compiler? The library solution provides the functionality and does so in a much more flexible manner than the compiler reasonably could. - Jonathan M DavisThere also really isn't a need to do so.If there was no need then C/C++ compilers wouldn't provide it as an option…
Sep 18 2017
On Monday, 18 September 2017 at 14:36:35 UTC, Jonathan M Davis wrote:We have std.experimental.checkedint, so why would there be any need for it to be in the compiler? The library solution provides the functionality and does so in a much more flexible manner than the compiler reasonably could.So that you can use third party libraries? Or debug your application?
Sep 18 2017
On Monday, 18 September 2017 at 08:27:21 UTC, Jonathan M Davis wrote:If you care about having the overflow checksOn Monday, 18 September 2017 at 08:27:21 UTC, Jonathan M Davis wrote:Personally, I've never had a need for checked ints. I've rarely seen code that would care, and when you do, it's usually pretty easy to deal with it properly. But Checked is there for those who feel the need.That we don't feel the need or care doesn't mean the problem doesn't exist. That's why I gave an example that I always felt was safe ( malloc(w*h)) but wasn't. I'd wager no native programmer feel the need for overflow checks or Checked!int, that's why we have security problems in the first place.
Sep 18 2017
On 09/15/2017 04:46 AM, Guillaume Piolat wrote:As a die-hard native programmer I was always disgusted by integer overflow checks and array bounds checks. Littering code with branches everywhere? Just let me go as fast possible please! Last week I was explained by security people how a part of vulnerabilities todays are attacks on image parsers, and how integer overflow checks may help there. IIRC a typical attack on image format parser is to forge an image with a width and height that will overflow an int. On allocation, the result of the multiplied wraps around like this: int width = parse_width_from_stream(); // eg: 131072 int height = parse_height_from_stream(); // eg: 131073 ubyte[] data = malloc(width * height * 4); // wraps around, allocates way less memory than thatFor the record, with the help of std.experimental.checkedint, the change that fixes the code would be: malloc(width * height * 4) ==> malloc((checked(width) * height * 4).get) That aborts the application with a message if a multiplication overflows. Andrei
Sep 18 2017
On Monday, 18 September 2017 at 13:25:55 UTC, Andrei Alexandrescu wrote:For the record, with the help of std.experimental.checkedint, the change that fixes the code would be: malloc(width * height * 4) ==> malloc((checked(width) * height * 4).get) That aborts the application with a message if a multiplication overflows.Can it do something other than abort? Can it throw an overflow exception that could be caught to report the error and continue? Dennis Cote
Sep 18 2017
On Monday, 18 September 2017 at 22:32:28 UTC, Dennis Cote wrote:On Monday, 18 September 2017 at 13:25:55 UTC, Andrei Alexandrescu wrote:Yes. Use one of the provided hooks (e.g. [1][2][3]) or write one that fits your use case. [1] https://dlang.org/phobos/std_experimental_checkedint.html#Abort [2] https://dlang.org/phobos/std_experimental_checkedint.html#Throw [3] https://dlang.org/phobos/std_experimental_checkedint.html#WarnFor the record, with the help of std.experimental.checkedint, the change that fixes the code would be: malloc(width * height * 4) ==> malloc((checked(width) * height * 4).get) That aborts the application with a message if a multiplication overflows.Can it do something other than abort? Can it throw an overflow exception that could be caught to report the error and continue?
Sep 18 2017
On Monday, September 18, 2017 22:39:09 Moritz Maxeiner via Digitalmars-d wrote:On Monday, 18 September 2017 at 22:32:28 UTC, Dennis Cote wrote:Yeah, it's really quite flexible with minimal code. Andrei talked about it in his dconf 2017 talk: https://www.youtube.com/watch?v=29h6jGtZD-U - Jonathan M DavisOn Monday, 18 September 2017 at 13:25:55 UTC, Andrei Alexandrescu wrote:Yes. Use one of the provided hooks (e.g. [1][2][3]) or write one that fits your use case. [1] https://dlang.org/phobos/std_experimental_checkedint.html#Abort [2] https://dlang.org/phobos/std_experimental_checkedint.html#Throw [3] https://dlang.org/phobos/std_experimental_checkedint.html#WarnFor the record, with the help of std.experimental.checkedint, the change that fixes the code would be: malloc(width * height * 4) ==> malloc((checked(width) * height * 4).get) That aborts the application with a message if a multiplication overflows.Can it do something other than abort? Can it throw an overflow exception that could be caught to report the error and continue?
Sep 18 2017