Bug 9975 – pointsTo asserts because of false pointer in union

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-04-21T05:42:00Z
Last change time
2014-05-23T18:44:31Z
Assigned to
monarchdodra
Creator
code

Comments

Comment #0 by code — 2013-04-21T05:42:44Z
import std.exception; struct S { union { size_t sz; string s; } } void main() { S a, b; a.sz = -1; assert(!pointsTo(a, b)); } ---- The problem is that pointsTo checks every .tupleof member thus the example asserts because a.s pointsTo b. http://www.digitalmars.com/d/archives/digitalmars/D/learn/overzealous_pointsTo_23203.html
Comment #1 by monarchdodra — 2013-04-24T14:20:12Z
But isn't this the expected behavior though? By setting sz to -1, s becomes a string (dynamic array), that starts at null, and spans size_t.max. So in that sense, b is inside a.sz, so a points to b. Looking at the provided link, where it shows that non anonymous unions don't show this "problem", I'm really tempted to say it actually reveils that pointsTo *doesn't* support unions correctly, as *both* asserts should have failed...
Comment #2 by monarchdodra — 2013-04-26T08:44:36Z
https://github.com/D-Programming-Language/phobos/pull/1277 Fix Issue 9975 - pointsTo asserts because of false pointer in union
Comment #3 by github-bugzilla — 2013-05-25T22:00:52Z
Commit pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/7518f83d0082e5cd339ef5d7c215f13a0287ad4b Do not include test case for issue 9975 It's not behavior that we guarantee.
Comment #4 by k.hara.pg — 2013-05-25T22:12:10Z
(In reply to comment #3) > Commit pushed to master at https://github.com/D-Programming-Language/dmd > > https://github.com/D-Programming-Language/dmd/commit/7518f83d0082e5cd339ef5d7c215f13a0287ad4b > Do not include test case for issue 9975 > > It's not behavior that we guarantee. The commit is not for this issue. Please ignore it.
Comment #5 by github-bugzilla — 2013-06-16T13:51:37Z
Commits pushed to master at https://github.com/D-Programming-Language/phobos https://github.com/D-Programming-Language/phobos/commit/e44adcd9edfd025fa7074501e1743e54ecbbda33 Fix Issue 9975 - pointsTo asserts because of false pointer in union https://github.com/D-Programming-Language/phobos/commit/af14a7f0aad058587fa498bbcdfd0ad84c204deb Merge pull request #1277 from monarchdodra/9975 Fix Issue 9975 - pointsTo asserts because of false pointer in union
Comment #6 by code — 2013-06-17T16:08:14Z
This function is used throughout std.algorithm so marking this as documented behavior is not a good solution because it mean basic algorithms like sort can't be used with such structs.
Comment #7 by monarchdodra — 2013-06-17T23:44:57Z
(In reply to comment #6) > This function is used throughout std.algorithm so marking this as documented > behavior is not a good solution because it mean basic algorithms like sort > can't be used with such structs. Which behavior exactly are you mentioning? And do you mean *any* structs, or just structs containing unions? As far as documentation goes, all I added was that when doing pointsTo on a union, you "could" get a false positive. I don't think there is any way around it, since pointsTo would have no way to know *which* members to check. That, and a false positive is always safer than a false negative. In case of the original example in this bug, it is not tested nor documented. Could you explain in more detail what you think is wrong and/or what should be changed?
Comment #8 by code — 2013-06-18T01:53:05Z
(In reply to comment #7) > (In reply to comment #6) > > This function is used throughout std.algorithm so marking this as documented > > behavior is not a good solution because it mean basic algorithms like sort > > can't be used with such structs. > > Which behavior exactly are you mentioning? And do you mean *any* structs, or > just structs containing unions? > Returning false positives. Any struct that might trigger false positives on pointsTo. It's really a serious issue, I stumbled over this while sorting JSON values. I don't think we can afford to say that sort or swap can't be used with algebraic types because they trigger false positive assertions. Of course this is mainly an issue with swap so we need to look at both sides. > Could you explain in more detail what you think is wrong and/or what should be changed? Maybe it's possible to mitigate the problem by reliably identifying that something can't be a valid pointer. But to really fix the swap issue we could make this configurable, i.e. either add an `ignoreFalsePointer` parameter or return a tri-state result. Then swap could at least work for most cases.
Comment #9 by monarchdodra — 2013-06-18T02:48:36Z
(In reply to comment #8) > (In reply to comment #7) > > (In reply to comment #6) > > > This function is used throughout std.algorithm so marking this as documented > > > behavior is not a good solution because it mean basic algorithms like sort > > > can't be used with such structs. > > > > Which behavior exactly are you mentioning? And do you mean *any* structs, or > > just structs containing unions? > > > Returning false positives. > Any struct that might trigger false positives on pointsTo. It'd be even worst to have a false negative, IMO. Of course, the best would be to not have any "false". > It's really a serious issue, I stumbled over this while sorting JSON values. > I don't think we can afford to say that sort or swap can't be used with > algebraic types because they trigger false positive assertions. > Of course this is mainly an issue with swap so we need to look at both sides. Just to be clear, algebraic types don't trigger false positives. The only things that answer true to pointsTo are true pointer types (including slices and classes). Everything other basic type is statically known not to be a pointer type. Basically, points to knows what is pointer type, and what isn't. There are (AFAIK) no "false pointers" The problem really only appears once unions get into the way. If a union contains an int, and a pointer (which is basically the example provided), then there is literally no way to know which of the union members should be taken into account. The union legitimately contains both the states pointsTo and !pointsTo :/ That's where the problem is. Given that pointsTo anser true as soon as at least a member pointsTo something, the reasonable answer to give in case of dual state is true... It *is* a problem, but I don't think it is as big a problem as you think it is (or at least, not in your wording of "sort can't be used with structs"). A tristate answer might be the answer. Given that pointsTo is mostly only ever used in assertive conditions, we could assert only if pointsTo is true. If pointsTo is "maybe", the swap can be more lenient and go ahead anyways...? We'd need to have a tribool type in phobos first though, if we want to do this in a (mostly) non breaking way.
Comment #10 by code — 2013-06-18T03:09:48Z
(In reply to comment #9) > It *is* a problem, but I don't think it is as big a problem as you think it is > (or at least, not in your wording of "sort can't be used with structs"). > These kind of things just have to work. auto result = get("http://example.com").parseJSON().sort!((a, b) => a["id"] < b["id"])();
Comment #11 by monarchdodra — 2013-06-18T07:40:38Z
(In reply to comment #10) > (In reply to comment #9) > > It *is* a problem, but I don't think it is as big a problem as you think it is > > (or at least, not in your wording of "sort can't be used with structs"). > > > > These kind of things just have to work. > > auto result = get("http://example.com").parseJSON().sort!((a, b) => a["id"] < > b["id"])(); That didn't compile for me, but I suppose it's supposed to assert in "swap" ? In any case, I'm not sure how to go about fixing this, it's either false negatives, or false positives. I looked into doing a tri-state answer, à la boost::tribool, however, this does not work in D at all (due to overloads being implemented in terms of others): (a != b) => !(a == b) (!a) => !cast(bool)a Maybe an extra parameter, eg "enums = {falsePositive, falseNegative}" could work? Or maybe we should just say that "pointsTo" is mostly only ever used in asserts, so prefers false negatives? I'll look into what I can provide...
Comment #12 by code — 2013-06-18T10:14:48Z
(In reply to comment #11) > > auto result = get("http://example.com").parseJSON().sort!((a, b) => a["id"] < > > b["id"])(); > > That didn't compile for me, but I suppose it's supposed to assert in "swap" ? > OK, it's a bit longer. And yes it might fail in swap. auto result = get("http://example.com").parseJSON.array.sort!((a, b) => a["id"].uinteger < b["id"].uinteger)(); I added Andrei to the CC list, maybe he has a good idea how to solve this.
Comment #13 by monarchdodra — 2013-06-18T11:21:51Z
(In reply to comment #12) > OK, it's a bit longer. And yes it might fail in swap. > > auto result = get("http://example.com").parseJSON.array.sort!((a, b) => > a["id"].uinteger < b["id"].uinteger)(); > > I added Andrei to the CC list, maybe he has a good idea how to solve this. I just thought of another problem (which is in the original message): While we might be able to special case named unions, we can't for anonymous unions. This means that what we have right now (unless I'm missing information), is the best we can do. I'm really just wondering what business swap has asserting if there are pointers to either of the members... Having such a pointer is a *sign* of stink, but I don't think it is 100% certifiably wrong... in which case it should not assert.
Comment #14 by monarchdodra — 2013-07-05T05:57:29Z
(In reply to comment #13) > I'm really just wondering what business swap has asserting if there are > pointers to either of the members... Having such a pointer is a *sign* of > stink, but I don't think it is 100% certifiably wrong... in which case it > should not assert. Done: https://github.com/D-Programming-Language/phobos/pull/1390
Comment #15 by github-bugzilla — 2014-05-23T18:44:29Z
Commit pushed to master at https://github.com/D-Programming-Language/phobos https://github.com/D-Programming-Language/phobos/commit/0ae323dc6f0eff18490cb6d58fc288870b154892 Merge pull request #2167 from monarchdodra/pointsTo Fix issues 9975 & 12479