On 27. 5. 2026 13:01, Timofei Zhakov wrote:
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 common knowledge. 😉

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...

The C standard only mentions a very limited set of warnings ("diagnostics"). Compilers are free to add their own, and MSVC is notorious for adding warnings for things that an experienced C programmer would find perfectly normal, such as the rules for integer value promotion. I'm guessing not very many experienced C programmers write in C for Windows/Win32 these days.

     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