Fix Entry in CheckVTableHasNoDuplicates().
The Entry constructor initialized Entry.name_len in a call
to another function as part of the Entry.name initialization
but given the order of members, the Entry.name_len was later
overwritten with 0. When the change
https://android-review.googlesource.com/1535207
replaced strcmp() with memcmp(), relying on Entry.name_len
being properly initialized, the equality comparison was
broken. We fix that by initializing Entry.name_len before
the Entry.name and also adjust it for non-ASCII characters.
Test: m dump-oat # No unexpected logs.
Bug: 175869411
Change-Id: I08f3425b4dac25adddc4f720c110d85533b99d8b
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 9003bc0..f3c58d3 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -7500,17 +7500,25 @@
// Need to check across dex files.
struct Entry {
size_t cached_hash = 0;
+ uint32_t name_len = 0;
const char* name = nullptr;
Signature signature = Signature::NoSignature();
- uint32_t name_len = 0;
Entry() = default;
Entry(const Entry& other) = default;
Entry& operator=(const Entry& other) = default;
Entry(const DexFile* dex_file, const dex::MethodId& mid)
- : name(dex_file->StringDataAndUtf16LengthByIdx(mid.name_idx_, &name_len)),
+ : name_len(0), // Explicit to enforce ordering with -Werror,-Wreorder-ctor.
+ // This call writes `name_len` and it is therefore necessary that the
+ // initializer for `name_len` comes before it, otherwise the value
+ // from the call would be overwritten by that initializer.
+ name(dex_file->StringDataAndUtf16LengthByIdx(mid.name_idx_, &name_len)),
signature(dex_file->GetMethodSignature(mid)) {
+ // The `name_len` has been initialized to the UTF16 length. Calculate length in bytes.
+ if (name[name_len] != 0) {
+ name_len += strlen(name + name_len);
+ }
}
bool operator==(const Entry& other) const {