Skip to content

Commit 73fabca

Browse files
committed
GH-1310 Loosen validation for freed objects in dictionary
1 parent 44ce9f4 commit 73fabca

2 files changed

Lines changed: 19 additions & 11 deletions

File tree

core/variant/container_type_validate.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
*/
4040

4141
#include "core/object/script_language.h"
42+
#include "core/typedefs.h"
4243
#include "core/variant/variant.h"
4344

4445
struct ContainerType {
@@ -55,7 +56,7 @@ struct ContainerTypeValidate {
5556

5657
private:
5758
/// Coerces String and StringName into each other and int into float when needed.
58-
_FORCE_INLINE_ bool _internal_validate(Variant &inout_variant, const char *p_operation, bool p_output_errors) const {
59+
_FORCE_INLINE_ bool _internal_validate(Variant &inout_variant, const char *p_operation, bool p_output_errors, bool p_allow_freed = false) const {
5960
if (type == Variant::NIL) {
6061
return true;
6162
}
@@ -86,10 +87,10 @@ struct ContainerTypeValidate {
8687
return true;
8788
}
8889

89-
return _internal_validate_object(inout_variant, p_operation, p_output_errors);
90+
return _internal_validate_object(inout_variant, p_operation, p_output_errors, p_allow_freed);
9091
}
9192

92-
_FORCE_INLINE_ bool _internal_validate_object(const Variant &p_variant, const char *p_operation, bool p_output_errors) const {
93+
_FORCE_INLINE_ bool _internal_validate_object(const Variant &p_variant, const char *p_operation, bool p_output_errors, bool p_allow_freed = false) const {
9394
ERR_FAIL_COND_V(p_variant.get_type() != Variant::OBJECT, false);
9495

9596
#ifdef DEBUG_ENABLED
@@ -99,6 +100,9 @@ struct ContainerTypeValidate {
99100
}
100101
Object *object = ObjectDB::get_instance(object_id);
101102
if (object == nullptr) {
103+
if (p_allow_freed) {
104+
return true;
105+
}
102106
if (p_output_errors) {
103107
ERR_FAIL_V_MSG(false, vformat("Attempted to %s an invalid (previously freed?) object instance into a '%s'.", String(p_operation), String(where)));
104108
} else {
@@ -154,6 +158,10 @@ struct ContainerTypeValidate {
154158
return _internal_validate(inout_variant, p_operation, true);
155159
}
156160

161+
_FORCE_INLINE_ bool validate_for_lookup(Variant &inout_variant, const char *p_operation = "use") const {
162+
return _internal_validate(inout_variant, p_operation, true, true);
163+
}
164+
157165
_FORCE_INLINE_ bool validate_object(const Variant &p_variant, const char *p_operation = "use") const {
158166
return _internal_validate_object(p_variant, p_operation, true);
159167
}

core/variant/dictionary.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ Variant &Dictionary::operator[](const Variant &p_key) {
128128

129129
const Variant &Dictionary::operator[](const Variant &p_key) const {
130130
Variant key = p_key;
131-
if (unlikely(!_p->typed_key.validate(key, "use `operator[]`"))) {
131+
if (unlikely(!_p->typed_key.validate_for_lookup(key, "use `operator[]`"))) {
132132
if (unlikely(!_p->typed_fallback)) {
133133
_p->typed_fallback = memnew(Variant);
134134
}
@@ -142,7 +142,7 @@ const Variant &Dictionary::operator[](const Variant &p_key) const {
142142

143143
const Variant *Dictionary::getptr(const Variant &p_key) const {
144144
Variant key = p_key;
145-
if (unlikely(!_p->typed_key.validate(key, "getptr"))) {
145+
if (unlikely(!_p->typed_key.validate_for_lookup(key, "getptr"))) {
146146
return nullptr;
147147
}
148148
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(key));
@@ -172,7 +172,7 @@ Variant *Dictionary::getptr(const Variant &p_key) {
172172

173173
Variant Dictionary::get_valid(const Variant &p_key) const {
174174
Variant key = p_key;
175-
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "get_valid"), Variant());
175+
ERR_FAIL_COND_V(!_p->typed_key.validate_for_lookup(key, "get_valid"), Variant());
176176
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::ConstIterator E(_p->variant_map.find(key));
177177

178178
if (!E) {
@@ -183,7 +183,7 @@ Variant Dictionary::get_valid(const Variant &p_key) const {
183183

184184
Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const {
185185
Variant key = p_key;
186-
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "get"), p_default);
186+
ERR_FAIL_COND_V(!_p->typed_key.validate_for_lookup(key, "get"), p_default);
187187
const Variant *result = getptr(key);
188188
if (!result) {
189189
return p_default;
@@ -225,14 +225,14 @@ bool Dictionary::is_empty() const {
225225

226226
bool Dictionary::has(const Variant &p_key) const {
227227
Variant key = p_key;
228-
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "use 'has'"), false);
228+
ERR_FAIL_COND_V(!_p->typed_key.validate_for_lookup(key, "use 'has'"), false);
229229
return _p->variant_map.has(key);
230230
}
231231

232232
bool Dictionary::has_all(const Array &p_keys) const {
233233
for (int i = 0; i < p_keys.size(); i++) {
234234
Variant key = p_keys[i];
235-
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "use 'has_all'"), false);
235+
ERR_FAIL_COND_V(!_p->typed_key.validate_for_lookup(key, "use 'has_all'"), false);
236236
if (!_p->variant_map.has(key)) {
237237
return false;
238238
}
@@ -253,7 +253,7 @@ Variant Dictionary::find_key(const Variant &p_value) const {
253253

254254
bool Dictionary::erase(const Variant &p_key) {
255255
Variant key = p_key;
256-
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "erase"), false);
256+
ERR_FAIL_COND_V(!_p->typed_key.validate_for_lookup(key), false);
257257
ERR_FAIL_COND_V_MSG(_p->read_only, false, "Dictionary is in read-only state.");
258258
return _p->variant_map.erase(key);
259259
}
@@ -572,7 +572,7 @@ const Variant *Dictionary::next(const Variant *p_key) const {
572572
return nullptr;
573573
}
574574
Variant key = *p_key;
575-
ERR_FAIL_COND_V(!_p->typed_key.validate(key, "next"), nullptr);
575+
ERR_FAIL_COND_V(!_p->typed_key.validate_for_lookup(key, "next"), nullptr);
576576
HashMap<Variant, Variant, VariantHasher, StringLikeVariantComparator>::Iterator E = _p->variant_map.find(key);
577577

578578
if (!E) {

0 commit comments

Comments
 (0)