]> git.ipfire.org Git - thirdparty/git.git/commitdiff
hashmap_for_each_entry(): workaround MSVC's runtime check failure #3
authorJunio C Hamano <gitster@pobox.com>
Wed, 30 Sep 2020 15:26:24 +0000 (15:26 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 30 Sep 2020 20:26:54 +0000 (13:26 -0700)
The OFFSETOF_VAR(var, member) macro is implemented in terms of
offsetof(typeof(*var), member) with compilers that know typeof(),
but its fallback implemenation compares &(var->member) and (var) and
count the distance in bytes, i.e.

    ((uintptr_t)&(var)->member - (uintptr_t)(var))

MSVC's runtime check, when fed an uninitialized 'var', flags this as
a use of an uninitialized variable (and that is legit---uninitialized
contents of 'var' is subtracted) in a debug build.

After auditing all 6 uses of OFFSETOF_VAR(), 1 of them does feed a
potentially uninitialized 'var' to the macro in the beginning of the
for() loop:

    #define hashmap_for_each_entry(map, iter, var, member) \
            for (var = hashmap_iter_first_entry_offset(map, iter, \
                                                    OFFSETOF_VAR(var, member)); \
                    var; \
                    var = hashmap_iter_next_entry_offset(iter, \
                                                    OFFSETOF_VAR(var, member)))

We can work around this by making sure that var has _some_ value
when OFFSETOF_VAR() is called.  Strictly speaking, it invites
undefined behaviour to use NULL here if we end up with pointer
comparison, but MSVC runtime seems to be happy with it, and most
other systems have typeof() and don't even need pointer comparison
fallback code.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
hashmap.h

index ef220de4c64dabceb01273147b04bf5ebe897879..b011b394fefe34f46d098f02f1e19fd987bb2476 100644 (file)
--- a/hashmap.h
+++ b/hashmap.h
@@ -449,7 +449,8 @@ static inline struct hashmap_entry *hashmap_iter_first(struct hashmap *map,
  * containing a @member which is a "struct hashmap_entry"
  */
 #define hashmap_for_each_entry(map, iter, var, member) \
-       for (var = hashmap_iter_first_entry_offset(map, iter, \
+       for (var = NULL, /* for systems without typeof */ \
+            var = hashmap_iter_first_entry_offset(map, iter, \
                                                OFFSETOF_VAR(var, member)); \
                var; \
                var = hashmap_iter_next_entry_offset(iter, \