Closed Bug 269823 Opened 20 years ago Closed 20 years ago

Invalid casts prevent compilation on 64-bit platforms with g++ 4.0 (gcc 4) (nsHttpConnectionMgr.cpp)

Categories

(SeaMonkey :: General, defect)

defect
Not set
normal

Tracking

(Not tracked)

VERIFIED FIXED

People

(Reporter: falk, Unassigned)

References

Details

(Keywords: 64bit)

Attachments

(3 files, 4 obsolete files)

User-Agent: Mozilla/5.0 (X11; U; Linux alpha; en-US; rv:1.7.5) Gecko/20041114 Firefox/1.0 (Debian package 1.0-2) Build Identifier: C++ does not allow to cast a pointer to an integer of smaller size. There are several instances of this in Mozilla's source. Note the NS_FT2_OFFSET macro is still completely unportable (it assumes null pointers are represented by zero, and invokes undefined behaviour on the null pointer dereferencing), but I suspect there must be a reason that somebody went so far out of their way to avoid offsetof from <stdlib.h>. Reproducible: Always Steps to Reproduce: Build mozilla-firefox CVS with g++ 4.0 on a 64-bit platform.
Attached patch Patch (obsolete) — Splinter Review
Component: General → Browser-General
Product: Firefox → Browser
Version: unspecified → Trunk
Assignee: firefox → general
Status: UNCONFIRMED → NEW
Ever confirmed: true
QA Contact: firefox.general → general
Attachment #165912 - Flags: review?(timeless)
Product: Browser → Seamonkey
could you split up this patch in a netwerk/ part and a part for the rest? Also, I'm really not happy about using a type that's deprecated (http://lxr.mozilla.org/seamonkey/source/nsprpub/pr/include/prtypes.h#486)
(In reply to comment #2) > could you split up this patch in a netwerk/ part and a part for the rest? Will do. > Also, I'm really not happy about using a type that's deprecated > (http://lxr.mozilla.org/seamonkey/source/nsprpub/pr/include/prtypes.h#486) Then what do you prefer? size_t?
I'd probably pick unsigned long or PRPtrDiff, but I'd like to hear wchang's opinion on it...
I agree that the PRWord and PRUword types are useful. We often need an integer type that is the same size as (or large enough to hold) a void*. What I don't like is their names. "Word" is very ambiguous. I'd rather define new types for this purpose with descriptive names. Perhaps PRIntptr and PRUintptr (modeled after C99's intptr_t and uintptr_t)? Until the new types are added, I recommend using PRSize (or NSPR's own PRUptrdiff) if you need an unsigned type and PRPtrdiff if you need a signed type. But if you want to use PRWord and PRUword, that's fine, too. By the way, the best way to elimiate this compiler warning is to use two typecasts: - listTarget->info = (guint)listAtom; + listTarget->info = (guint)(PRUword)listAtom; The first cast makes the compiler let us cast a pointer to an integer type. The second cast eliminates the compiler warning about assigning to an integer type of a smaller size.
Re: the suggestion of using unsigned long in comment 4 unsigned long may not be large enough to hold a pointer. A counterexample is 64-bit Windows, where long is still 32-bit. So we need a type that is specifically defined to be the same size as (or large enough to hold) a pointer.
I would support a PRIntPtr type, yeah. C# has its own IntPtr for exactly this purpose, and the C99 types are just like this as well. I'd probably even review the tree-wide patch to change our PRWord usages!
This still uses PRUword to facilitate batch changing to PRIntPtr.
Attachment #165912 - Attachment is obsolete: true
Attachment #173171 - Flags: review?(darin)
Attached patch Patch for bad casts (gtk2 part) (obsolete) — Splinter Review
This still uses PRUword to facilitate batch changing to PRIntPtr.
Attachment #173172 - Flags: review?(bryner)
Comment on attachment 173171 [details] [diff] [review] Patch for bad casts (netwerk part) >- PRUint16 name = (PRUint32(param) & 0xFFFF0000) >> 16; >- PRUint16 value = PRUint32(param) & 0x0000FFFF; >+ PRUint16 name = (PRUword(param) & 0xFFFF0000) >> 16; >+ PRUint16 value = PRUword(param) & 0x0000FFFF; perhaps another choice would be to use the NS_PTR_TO_INT32 macro. notice that prtypes.h says: ** WARNING: The undocumented data types PRWord and PRUword are ** only used in the garbage collection and arena code. Do not ** use PRWord and PRUword in new code. so, perhaps you should head that warning?
oh, i should have read the rest of the comments in this bug... wtc, shaver: what do you guys think of NS_PTR_TO_INT32? that seems to be exactly what we want here.
(In reply to comment #11) > oh, i should have read the rest of the comments in this bug... > > wtc, shaver: what do you guys think of NS_PTR_TO_INT32? that seems to be > exactly what we want here. Ugh. Firstly, using signed integers here has implementation defined behaviour. Secondly, this macro is defined as #define NS_PTR_TO_INT32(x) ((char *)(x) - (char *)0) which is clearly invalid, and not unlikely to confuse a sufficiently advanced optimizer. Oh well.
The NS_PTR_TO_INT32 macro has a descriptive name and is exactly what we are doing here. The current definition (using pointer difference) of that macro does look ugly. A macro is nice because as I explained in comment 5, this may require two casts to eliminate compiler warnings (I'm using C99 types in the example below): #define NS_PTR_TO_INT32(x) ((int32_t)(intptr_r)(x)) I found that intptr_t and uintptr_t are optional data types because an implementation may not have any integer type large enough to hold a pointer. It's very unusual though.
Looking in CVS history, I found that the NS_PTR_TO_INT32 macro was added in rev. 1.43 of nscore.h: 1.43 <cls@seawood.org> 2001-08-13 21:14 Adding NS_PTR_TO_INT32 & NS_INT32_TO_PTR macros to do safe pointer casting on 64-bit platforms. Bug #20860 r=Roland.Mainz@informatik.med.uni-giessen.de sr=brendan@mozilla.org Since intptr_t and uintptr_t are only optional types, I don't think there is a fully portable definition of NS_PTR_TO_INT32. So how we want to define this macro is going to be a matter of personal experience and preference.
Attachment #165912 - Flags: review?(timeless)
how about we modify NS_PTR_TO_INT32 and create NS_PTR_TO_UINT32 so that we have something that works as desired, and then use that instead of PRUword. Sound like a plan?
Attachment #173171 - Flags: review?(darin) → review-
I agree it's better to hide the casts in a macro.
*** Bug 281576 has been marked as a duplicate of this bug. ***
Summary: Invalid casts prevent compilation on 64-bit platforms with g++ 4.0 → Invalid casts prevent compilation on 64-bit platforms with g++ 4.0 (nsHttpConnectionMgr.cpp)
*** Bug 284649 has been marked as a duplicate of this bug. ***
Comment on attachment 173172 [details] [diff] [review] Patch for bad casts (gtk2 part) minusing per the prior discussion on the bug.
Attachment #173172 - Flags: review?(bryner) → review-
Please note that bug 284809 also tries to correct this (and other gcc4.0 +amd64 issues) They mostly uses "NS_PTR_TO_INT32" as far as I can see. should one of the bugs be closed as a duplicate ?
*** Bug 296792 has been marked as a duplicate of this bug. ***
*** Bug 284809 has been marked as a duplicate of this bug. ***
Summary: Invalid casts prevent compilation on 64-bit platforms with g++ 4.0 (nsHttpConnectionMgr.cpp) → Invalid casts prevent compilation on 64-bit platforms with g++ 4.0 (gcc 4) (nsHttpConnectionMgr.cpp)
*** Bug 298259 has been marked as a duplicate of this bug. ***
I wanted to make note that ever since I applied the upcast-downcast patch, my text cursor no longer works inside textarea, input[@type='text'] or the address bar. I don't have any proof (or way of obtaining it short of a checkout of last week's HEAD and building it with these same patches), but found it a strange coincidence. My .mozconfig hasn't changed in quite a while (since the cairo config change).
Following comment #15, this avoids undefined behavior in NS_PTR_TO_INT32 and NS_INT32_TO_PTR. It also makes NS_PTR_TO_INT32 actually return a 32-bit integer instead of a ptrdiff_t, which might be 64-bit. NS_PTR_TO_UINT32 is added for places where an uint32 is required to avoid implementation defined int32->uint32 casts.
Attachment #173171 - Attachment is obsolete: true
Attachment #173172 - Attachment is obsolete: true
Attachment #187644 - Flags: review?(darin)
Comment on attachment 187644 [details] [diff] [review] Fix NS_PTR_TO_INT32 and NS_INT32_TO_PTR, add NS_PTR_TO_UINT32 >-#define NS_PTR_TO_INT32(x) ((char *)(x) - (char *)0) >+#define NS_PTR_TO_INT32(x) ((PRInt32) (PRWord) (x)) C++ allows you to cast a ptrdiff_t to an int, right? So, why not modify the macros like so: #define NS_PTR_TO_INT32(x) PRInt32((char *)(x) - (char *)0) ?
(In reply to comment #28) > C++ allows you to cast a ptrdiff_t to an int, right? So, why not > modify the macros like so: > > #define NS_PTR_TO_INT32(x) PRInt32((char *)(x) - (char *)0) Because this is undefined behavior. Pointer difference is only valid for two pointers into the same array, or one behind the end. This is not only a hypothetical problem. For example, the compiler can decuce that x is nonzero here and optimize a further (x != 0) away. So this code is playing a very dangerous game, for no good reason.
Comment on attachment 187644 [details] [diff] [review] Fix NS_PTR_TO_INT32 and NS_INT32_TO_PTR, add NS_PTR_TO_UINT32 OK, thanks for the explanation. r=darin
Attachment #187644 - Flags: review?(darin) → review+
Comment on attachment 187647 [details] [diff] [review] Patch for bad casts (gtk2 part, using NS_PTR_TO_UINT32) Should this use GPOINTER_TO_UINT instead, since it's all in gtk2-related code? That's what I did in my tree, at least.
(In reply to comment #31) > (From update of attachment 187647 [details] [diff] [review] [edit]) > Should this use GPOINTER_TO_UINT instead, since it's all in gtk2-related code? I guess it should; I simply didn't know that macro. Can you attach a new patch?
Comment on attachment 187644 [details] [diff] [review] Fix NS_PTR_TO_INT32 and NS_INT32_TO_PTR, add NS_PTR_TO_UINT32 sr+a=shaver, I'll commit this patch.
Attachment #187644 - Flags: superreview+
Attachment #187644 - Flags: approval1.8b4+
This is what I'm building with now. caillon: can you gimme a stamp?
Attachment #187647 - Attachment is obsolete: true
Attachment #189883 - Flags: superreview?(caillon)
Attachment #189883 - Flags: review?(caillon)
Attachment #189883 - Flags: approval1.8b4+
Attachment #189883 - Flags: superreview?(caillon)
Attachment #189883 - Flags: review?(caillon)
Attachment #189883 - Flags: review+
Attachment #187646 - Flags: review+
Comment on attachment 187646 [details] [diff] [review] Patch for bad casts (netwerk part, using NS_PTR_TO_UINT32) sr+a=shaver, though I don't really understand why we have the masking there as well as the shift. I'll commit this ASAP.
Attachment #187646 - Flags: superreview+
Attachment #187646 - Flags: approval1.8b4+
Fixed, woo.
Status: NEW → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
Status: RESOLVED → VERIFIED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: