summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <rverschelde@gmail.com>2019-04-01 17:00:40 +0200
committerGitHub <noreply@github.com>2019-04-01 17:00:40 +0200
commite3bd84fa571661d76fc8458d65bb053988e934a6 (patch)
treecbf6ead84d9e62d331f5399e6407f9e6777425a3 /modules/gdscript
parente91844e8dca5d03eabd33e867fdbceb18db60cff (diff)
parent393e62b98a5a37ccdd7d860571e2f8cc7b970fe4 (diff)
Merge pull request #27485 from Faless/io/encode_decode_safety_pr
Safer encode/decode variant.
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/gdscript_functions.cpp57
-rw-r--r--modules/gdscript/gdscript_tokenizer.cpp8
2 files changed, 54 insertions, 11 deletions
diff --git a/modules/gdscript/gdscript_functions.cpp b/modules/gdscript/gdscript_functions.cpp
index 44d44462ca..46c9efd54f 100644
--- a/modules/gdscript/gdscript_functions.cpp
+++ b/modules/gdscript/gdscript_functions.cpp
@@ -768,11 +768,30 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
(void)VariantParser::parse(&ss, r_ret, errs, line);
} break;
case VAR_TO_BYTES: {
- VALIDATE_ARG_COUNT(1);
+ bool full_objects = false;
+ if (p_arg_count < 1) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ r_ret = Variant();
+ return;
+ } else if (p_arg_count > 2) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = 2;
+ r_ret = Variant();
+ } else if (p_arg_count == 2) {
+ if (p_args[1]->get_type() != Variant::BOOL) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::BOOL;
+ r_ret = Variant();
+ return;
+ }
+ full_objects = *p_args[1];
+ }
PoolByteArray barr;
int len;
- Error err = encode_variant(*p_args[0], NULL, len);
+ Error err = encode_variant(*p_args[0], NULL, len, full_objects);
if (err) {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
r_error.argument = 0;
@@ -784,15 +803,35 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
barr.resize(len);
{
PoolByteArray::Write w = barr.write();
- encode_variant(*p_args[0], w.ptr(), len);
+ encode_variant(*p_args[0], w.ptr(), len, full_objects);
}
r_ret = barr;
} break;
case BYTES_TO_VAR: {
- VALIDATE_ARG_COUNT(1);
+ bool allow_objects = false;
+ if (p_arg_count < 1) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ r_ret = Variant();
+ return;
+ } else if (p_arg_count > 2) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS;
+ r_error.argument = 2;
+ r_ret = Variant();
+ } else if (p_arg_count == 2) {
+ if (p_args[1]->get_type() != Variant::BOOL) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = 1;
+ r_error.expected = Variant::BOOL;
+ r_ret = Variant();
+ return;
+ }
+ allow_objects = *p_args[1];
+ }
+
if (p_args[0]->get_type() != Variant::POOL_BYTE_ARRAY) {
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
- r_error.argument = 0;
+ r_error.argument = 1;
r_error.expected = Variant::POOL_BYTE_ARRAY;
r_ret = Variant();
return;
@@ -802,7 +841,7 @@ void GDScriptFunctions::call(Function p_func, const Variant **p_args, int p_arg_
Variant ret;
{
PoolByteArray::Read r = varr.read();
- Error err = decode_variant(ret, r.ptr(), varr.size(), NULL);
+ Error err = decode_variant(ret, r.ptr(), varr.size(), NULL, allow_objects);
if (err != OK) {
r_ret = RTR("Not enough bytes for decoding bytes, or invalid format.");
r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
@@ -1805,13 +1844,15 @@ MethodInfo GDScriptFunctions::get_info(Function p_func) {
} break;
case VAR_TO_BYTES: {
- MethodInfo mi("var2bytes", PropertyInfo(Variant::NIL, "var", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT));
+ MethodInfo mi("var2bytes", PropertyInfo(Variant::NIL, "var", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT), PropertyInfo(Variant::BOOL, "full_objects"));
+ mi.default_arguments.push_back(false);
mi.return_val.type = Variant::POOL_BYTE_ARRAY;
return mi;
} break;
case BYTES_TO_VAR: {
- MethodInfo mi(Variant::NIL, "bytes2var", PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes"));
+ MethodInfo mi(Variant::NIL, "bytes2var", PropertyInfo(Variant::POOL_BYTE_ARRAY, "bytes"), PropertyInfo(Variant::BOOL, "allow_objects"));
+ mi.default_arguments.push_back(false);
mi.return_val.type = Variant::NIL;
mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
return mi;
diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp
index 8b22d6f085..8962e3bb34 100644
--- a/modules/gdscript/gdscript_tokenizer.cpp
+++ b/modules/gdscript/gdscript_tokenizer.cpp
@@ -1199,7 +1199,8 @@ Error GDScriptTokenizerBuffer::set_code_buffer(const Vector<uint8_t> &p_buffer)
Variant v;
int len;
- Error err = decode_variant(v, b, total_len, &len);
+ // An object cannot be constant, never decode objects
+ Error err = decode_variant(v, b, total_len, &len, false);
if (err)
return err;
b += len;
@@ -1367,11 +1368,12 @@ Vector<uint8_t> GDScriptTokenizerBuffer::parse_code_string(const String &p_code)
for (Map<int, Variant>::Element *E = rev_constant_map.front(); E; E = E->next()) {
int len;
- Error err = encode_variant(E->get(), NULL, len);
+ // Objects cannot be constant, never encode objects
+ Error err = encode_variant(E->get(), NULL, len, false);
ERR_FAIL_COND_V(err != OK, Vector<uint8_t>());
int pos = buf.size();
buf.resize(pos + len);
- encode_variant(E->get(), &buf.write[pos], len);
+ encode_variant(E->get(), &buf.write[pos], len, false);
}
for (Map<int, uint32_t>::Element *E = rev_line_map.front(); E; E = E->next()) {