D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 10124 - Array length increases on subtraction of a big number instead of throwing RangeError
Summary: Array length increases on subtraction of a big number instead of throwing Ran...
Status: RESOLVED WONTFIX
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 normal
Assignee: No Owner
URL:
Keywords: backend, wrong-code
Depends on:
Blocks: 10123
  Show dependency treegraph
 
Reported: 2013-05-20 04:52 UTC by Denis Shelomovskii
Modified: 2020-08-29 07:08 UTC (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Denis Shelomovskii 2013-05-20 04:52:02 UTC
This code runs fine but should fail in runtime:
---
void main()
{
    int[] arr;
    arr.length -= size_t.max; // Let's subtract a very big number
    assert(arr.length == 1); // Passes!
}
---

Also there is a question what to do with `arr.length -= -1`? I'd like this code to be rejected as incorrect mixed signed/unsigned operation (see also Issue 259).

This is a compiler bug as dmd just calls `_d_arraysetlengthT` without any information about operation type. I.e. it works like `arr.length = arr.length - size_t.max`.
Comment 1 yebblies 2014-08-31 13:47:15 UTC
I'm not sure it should fail.  This is how unsigned types usually work.
Comment 2 monarchdodra 2014-08-31 21:03:55 UTC
(In reply to yebblies from comment #1)
> I'm not sure it should fail.  This is how unsigned types usually work.

Yeah... but it's not actually an arithmetic operations here. It's a setter operation. AFAIK, array resize detects overflow. I don't see why it wouldn't detect underflow?

Just saying.
Comment 3 Marco Leise 2014-09-01 06:44:08 UTC
I see it like the others, Denis. Detecting overflow/underflow here is no different than on regular integer math in other places. The compiler's rewrite looks fine to me. If anything, we need a generic integer overflow check placed around integer math.

Same goes for `arr.length -= -1': Again, this is how the language works. Mixing signed and unsigned is allowed, as is `a - (-1)'. While I am positive on these features in general as a nice-to-have, I think this bug report on array.length is invalid and too narrow. Consider for example some custom struct exposing some .length similar to arr.length, which would not be affected by a fix to this bug. We would get different semantics where we are striving to unify the experience.
Comment 4 yebblies 2014-09-01 18:18:40 UTC
Overflow looks the same:

void main()
{
    int[] arr = [1,2,3,4];
    arr.length += uint.max;
}

It's currently being rewritten to 'length = (length op arg)'.  I'm not sure how to detect this easily without adding inline code, or an overload for each operation.

I mean, for this:
    arr.length += -3;

the compiler sees this:
    arr.length = arr.length + 4294967293u;
Comment 5 Walter Bright 2020-08-29 07:08:06 UTC
This is an artifact of 2's complement arithmetic. Instrumenting the code to detect integer arithmetic overflows will have a large performance penalty, so is not done.