On Wed, May 27, 2026 at 11:28 AM Branko Čibej <[email protected]> wrote:

> On 27. 5. 2026 10:28, Timofei Zhakov wrote:
>
> On Tue, May 26, 2026 at 6:27 PM Branko Čibej <[email protected]> wrote:
>
>> On 26. 5. 26 18:09, [email protected] wrote:
>>
>> Author: ivan
>> Date: Tue May 26 16:09:14 2026
>> New Revision: 1934646
>>
>> Log:
>> Resolve compiler warning (C4312: 'type cast': conversion from 'unsigned int'
>> to 'void *' of greater size).
>>
>> * subversion/libsvn_repos/rev_hunt.c
>>   (find_interesting_revisions): Use "1" instead of 0xdeadbeef as non-null
>>    pointer for hashtable.
>>
>> Modified:
>>    subversion/trunk/subversion/libsvn_repos/rev_hunt.c
>>
>> Modified: subversion/trunk/subversion/libsvn_repos/rev_hunt.c
>> ==============================================================================
>> --- subversion/trunk/subversion/libsvn_repos/rev_hunt.c      Tue May 26 
>> 15:32:31 2026        (r1934645)
>> +++ subversion/trunk/subversion/libsvn_repos/rev_hunt.c      Tue May 26 
>> 16:09:14 2026        (r1934646)
>> @@ -1198,7 +1198,7 @@ find_interesting_revisions(apr_array_hea
>>        svn_hash_sets(duplicate_path_revs,
>>                      apr_psprintf(result_pool, "%s:%ld", path_rev->path,
>>                                   path_rev->revnum),
>> -                    (void *)0xdeadbeef);
>> +                    "1");
>>
>>        if (path_rev->revnum <= start)
>>          break;
>>
>>
>> That dead beef was there because we're using the hash table as a set, not
>> a dictionary; only the keys matter. It was intentionally an invalid pointer
>> so that the code would crash in a very recognisable way (better than NULL)
>> if someone ever tried to dereference the value from the hash table. If
>> you're fixing some useless compiler warning – frankly, a promotion that
>> doesn't lose data shouldn't warn at all, this is C, after all – then at
>> least replace it with NULL instead of a valid pointer that could one day
>> hide a real bug.
>>
>> Yes, I understand that not everyone likes my approach to defence against
>> incorrect code. :)
>>
>>
> Do I misunderstand something or since when on Earth do we have
> restrictions to assign a 32bit value to a 64bit variable (not the other
> way) which doesn't truncate any data?
>
> From the documentation about this warning
> https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-1-c4312
> :
>
> [[[
> This warning detects an attempt to assign a 32-bit value to a 64-bit
> pointer type, for example, casting a 32-bit int or long to a 64-bit pointer.
>
> This can be an unsafe conversion even for pointer values that fit in 32
> bits when sign extension occurs. If a negative 32-bit integer is assigned
> to a 64-bit pointer type, sign extension causes the pointer value to
> reference a memory address different from the value of the integer.
> ]]]
>
> If as the article says it's about the signed values, would casting it to
> an unsigned int and then to void* fix it? I mean to do something like:
>
> [[[
> (void *)(unsigned int)0xdeadbeef
> ]]]
>
> Also the same article suggests an example that it's okay to do the same
> thing with an int64. I assume the same is true about a size_t. It could
> also be a way to shut the compiler up.
>
>
> Maybe (void *)(uintptr_t)0xdeadbeef
>
> MSVC has inttypes.h these days and there's a standard pointer-sized
> unsigned integer type. So why not use it.
>

I guess it's not really in the C standard. In [2] it's listed as
"optional". Though I didn't know about this type :-)

It could be too much, but what do you think about a macro like
SVN__DEAD_POINTER that expands to this magic cast?


> Okay, technically casting a magic number to a pointer is in fact an
> undefined behaviour
>
>
> Ha. No, it's not. Using that pointer may invoke interesting
> *implementation-defined* behaviour. Just setting its value without
> dereferencing it is ... OK, though slightly on the exciting side: [1]
>
> Any integer can be cast to any pointer type. Except for the null pointer
> constants such as NULL (which doesn't need a cast), the result is
> implementation-defined, may not be correctly aligned, may not point to an
> object of the referenced type, and may be a trap representation.
>
>
>
>
That's a nice find!

It's still not so clear how it deals with signed values. I guess "any
integer" means that it doesn't care. So it seems like MSVC is the one not
following the specification with this warning...

 but here it is the idea so if anyone ever tries to dereference it, it
> leads to a crash. I guess NULL also doesn't work because apr_hash_get()
> already returns NULL if the key is not present.
>
>
> Which is probably why I used something other than NULL in the first place,
> yes.
>
> -- Brane
>
> [1] https://en.cppreference.com/c/language/cast
>

[2] https://en.cppreference.com/cpp/types/integer

-- 
Timofei Zhakov

Reply via email to