From a1918e7e9d1585587be270183866797eb1c682f5 Mon Sep 17 00:00:00 2001 From: Haru Date: Thu, 6 Feb 2014 21:12:36 +0100 Subject: Corrected same-reference check to work on vars with the same name in different scopes - Fixes bugreport:8008, special thanks to KeyWorld http://hercules.ws/board/tracker/issue-8008-copyarray-fail-on-a-referenced-array-argument/ Signed-off-by: Haru --- src/map/script.c | 25 +++++++++++-------------- src/map/script.h | 7 +++++++ 2 files changed, 18 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/map/script.c b/src/map/script.c index bf6dd448a..bef5f37e0 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -5770,30 +5770,27 @@ BUILDIN(copyarray) count = script_getnum(st, 4); if( count > SCRIPT_MAX_ARRAYSIZE - idx1 ) count = SCRIPT_MAX_ARRAYSIZE - idx1; - if( count <= 0 || (id1 == id2 && idx1 == idx2) ) + if( count <= 0 || (idx1 == idx2 && is_same_reference(data1, data2)) ) return true;// nothing to copy - if( id1 == id2 && idx1 > idx2 ) - {// destination might be overlapping the source - copy in reverse order - for( i = count - 1; i >= 0; --i ) - { + if( is_same_reference(data1, data2) && idx1 > idx2 ) { + // destination might be overlapping the source - copy in reverse order + for( i = count - 1; i >= 0; --i ) { v = script->get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2)); script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1)); script_removetop(st, -1, 0); } - } - else - {// normal copy - for( i = 0; i < count; ++i ) - { - if( idx2 + i < SCRIPT_MAX_ARRAYSIZE ) - { + } else { + // normal copy + for( i = 0; i < count; ++i ) { + if( idx2 + i < SCRIPT_MAX_ARRAYSIZE ) { v = script->get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2)); script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1)); script_removetop(st, -1, 0); - } - else// out of range - assume ""/0 + } else { + // out of range - assume ""/0 script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, (is_string_variable(name1)?(void*)"":(void*)0), reference_getref(data1)); + } } } return true; diff --git a/src/map/script.h b/src/map/script.h index ae851a7ec..ff947bf79 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -144,6 +144,13 @@ struct eri; /// Composes the uid of a reference from the id and the index #define reference_uid(id,idx) ( (int64) ((uint64)(id) & 0xFFFFFFFF) | ((uint64)(idx) << 32) ) +/// Checks whether two references point to the same variable (or array) +#define is_same_reference(data1, data2) \ + ( reference_getid(data1) == reference_getid(data2) \ + && ( (data1->ref == data2->ref && data1->ref == NULL) \ + || (data1->ref != NULL && data2->ref != NULL && data1->ref->vars == data2->ref->vars \ + ) ) ) + #define script_getvarid(var) ( (int32)(int64)(var & 0xFFFFFFFF) ) #define script_getvaridx(var) ( (uint32)(int64)((var >> 32) & 0xFFFFFFFF) ) -- cgit v1.2.3-70-g09d2