Skip to content

Commit

Permalink
[3.x] Core: Add recursion level check for Array and Dictionary ha…
Browse files Browse the repository at this point in the history
…shing
  • Loading branch information
dalexeev committed Aug 22, 2023
1 parent 17b403a commit 68e8c1b
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 8 deletions.
11 changes: 10 additions & 1 deletion core/array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,25 @@ bool Array::operator==(const Array &p_array) const {
}

uint32_t Array::hash() const {
return recursive_hash(0);
}

uint32_t Array::recursive_hash(int p_recursion_count) const {
ERR_FAIL_COND_V_MSG(p_recursion_count > MAX_RECURSION, 0, "Max recursion reached");
p_recursion_count++;

uint32_t h = hash_djb2_one_32(0);

for (int i = 0; i < _p->array.size(); i++) {
h = hash_djb2_one_32(_p->array[i].hash(), h);
h = hash_djb2_one_32(_p->array[i].recursive_hash(p_recursion_count), h);
}
return h;
}

void Array::operator=(const Array &p_array) {
_ref(p_array);
}

void Array::push_back(const Variant &p_value) {
_p->array.push_back(p_value);
}
Expand Down
1 change: 1 addition & 0 deletions core/array.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class Array {
bool operator==(const Array &p_array) const;

uint32_t hash() const;
uint32_t recursive_hash(int p_recursion_count) const;
void operator=(const Array &p_array);

void push_back(const Variant &p_value);
Expand Down
12 changes: 10 additions & 2 deletions core/dictionary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,20 @@ void Dictionary::_unref() const {
}
_p = nullptr;
}

uint32_t Dictionary::hash() const {
return recursive_hash(0);
}

uint32_t Dictionary::recursive_hash(int p_recursion_count) const {
ERR_FAIL_COND_V_MSG(p_recursion_count > MAX_RECURSION, 0, "Max recursion reached");
p_recursion_count++;

uint32_t h = hash_djb2_one_32(Variant::DICTIONARY);

for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) {
h = hash_djb2_one_32(E.key().hash(), h);
h = hash_djb2_one_32(E.value().hash(), h);
h = hash_djb2_one_32(E.key().recursive_hash(p_recursion_count), h);
h = hash_djb2_one_32(E.value().recursive_hash(p_recursion_count), h);
}

return h;
Expand Down
1 change: 1 addition & 0 deletions core/dictionary.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class Dictionary {
bool operator!=(const Dictionary &p_dictionary) const;

uint32_t hash() const;
uint32_t recursive_hash(int p_recursion_count) const;
void operator=(const Dictionary &p_dictionary);

const Variant *next(const Variant *p_key = nullptr) const;
Expand Down
11 changes: 6 additions & 5 deletions core/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2508,6 +2508,10 @@ Variant::~Variant() {
}*/

uint32_t Variant::hash() const {
return recursive_hash(0);
}

uint32_t Variant::recursive_hash(int p_recursion_count) const {
switch (type) {
case NIL: {
return 0;
Expand Down Expand Up @@ -2622,13 +2626,10 @@ uint32_t Variant::hash() const {
return reinterpret_cast<const NodePath *>(_data._mem)->hash();
} break;
case DICTIONARY: {
return reinterpret_cast<const Dictionary *>(_data._mem)->hash();

return reinterpret_cast<const Dictionary *>(_data._mem)->recursive_hash(p_recursion_count);
} break;
case ARRAY: {
const Array &arr = *reinterpret_cast<const Array *>(_data._mem);
return arr.hash();

return reinterpret_cast<const Array *>(_data._mem)->recursive_hash(p_recursion_count);
} break;
case POOL_BYTE_ARRAY: {
const PoolVector<uint8_t> &arr = *reinterpret_cast<const PoolVector<uint8_t> *>(_data._mem);
Expand Down
1 change: 1 addition & 0 deletions core/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ class Variant {
bool operator!=(const Variant &p_variant) const;
bool operator<(const Variant &p_variant) const;
uint32_t hash() const;
uint32_t recursive_hash(int p_recursion_count) const;

bool hash_compare(const Variant &p_variant) const;
bool booleanize() const;
Expand Down

0 comments on commit 68e8c1b

Please sign in to comment.