www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 1875] New: &null[x] compiles and runs, giving x

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1875

           Summary: &null[x] compiles and runs, giving x
           Product: D
           Version: 1.027
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Keywords: accepts-invalid, spec
          Severity: trivial
          Priority: P5
         Component: DMD
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: matti.niemenmaa+dbugzilla iki.fi


import std.stdio;
void main() {
        writefln(&null[42]);
}

The above prints "002A" - i.e. the hexadecimal representation of 42, the value
used to index null.

This is, I'm fairly certain, unspecified behaviour, but I think you'd be hard
pressed to argue that this makes sense in any way. I'm marking this as
"accepts-invalid" but also as "trivial" since I honestly hope that nobody else
has ever dreamed of doing something like this. :-)

The issue is essentially: why does null[x] return a void type, and why is
taking its address a valid operation? In addition, why is indexing null valid
in the first place? Trying the same with [][x] results in out-of-bounds errors
at compile time.

Note that this works even at runtime, for any value of x.


-- 
Feb 27 2008
next sibling parent reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1875







&null[47] -> &(null[47]) -> (null + 47) -> (0 + 47) -> 47

Why is that unexpected? What should it do? if that null is not a literal the
only way to check would be to do a read but that can have problems of it's own.

also; null is a pointer. all pointers are indexable. -> null is indexable*

also it it's a way to avoid a cast for constant pointers. (Not saying it's a
good idea...)

void* HW_ptr = &null[0xf000];


* the phrasing is so classic I couldn't resist the last bit.


-- 
Feb 27 2008
parent "Lionello Lunesu" <lionello lunesu.remove.com> writes:
 also; null is a pointer. all pointers are indexable. -> null is indexable*
Apparently they are, but should they be? void main() { void* va; auto x = &va[2]; } This compiles just fine (2.011) but should indexing a void* (and therefor: null) even be allowed? L.
Feb 27 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1875






-------
I don't think it makes sense for void pointers to be indexable, just like they
aren't in C.

For that matter, I think indexing pointer constants in general deserves a
warning, at least. For the case of null, it should be an error: why is indexing
cast(int[])null an array bounds error, but indexing null as a pointer isn't? In
both cases, you know there are no valid elements there - that's the definition
of the null pointer.

You'll note that the results are unpredictable: &null[420] is 420, but
&(cast(int*)null)[420] is 1680 - that's int.sizeof * 420. And similarly, for a
long, you get 3360.


-- 
Feb 27 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1875


matti.niemenmaa+dbugzilla iki.fi changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|trivial                     |enhancement
           Keywords|accepts-invalid, spec       |diagnostic
         OS/Version|Windows                     |All
           Platform|PC                          |All
            Summary|&null[x] compiles and runs, |Dereferencing void pointers
                   |giving x                    |is allowed





-------
Hmm, no: the more I think about this the more I think I'm wrong. I shouldn't
file bugs at midnight.

I'll leave this as an enhancement request for a warning on dereferencing void
pointers.


-- 
Feb 27 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1875






Um.. at no point in this code has anything been dereferenced.  The only thing
occurring here is pointer math (against 0, but still just math).  Further, it
actually _is_ legal in both c and c++.  In fact, the offsetof macro is built
around that capability:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)


-- 
Feb 27 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1875






-------
Which is why I said I was wrong. I realize that.

However, I do think there's a dereference going on - even if it's undone by the
& to the point that the dereference isn't in the resulting binary. "&
(null[x])" is "& *(null + x)" which means that, essentially, "null + x" is
being dereferenced.

Your code is different: that's not a void pointer, it's a type-casted null
pointer.

GCC gives a "warning: dereferencing 'void *' pointer" for the following C code:

#include <stdlib.h>
int main() {
        return (int)&NULL[42];
}

Which is all I ask for. Feel free to mark as WONTFIX if you think that's not
going to happen.


-- 
Feb 28 2008
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=1875


bugzilla digitalmars.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |WONTFIX





I don't agree there's a dereference going on unless the result of a folded
expression actually does a dereference. At best, it is just an intermediate
state in a calculation. Since it's a difference of opinion, I'll just mark it
as 'wontfix'.


-- 
Feb 28 2008