Explorar o código

prevent setting a field with a stack allocated vdynamic (close #261)

Nicolas Cannasse %!s(int64=6) %!d(string=hai) anos
pai
achega
9eed29b17f
Modificáronse 4 ficheiros con 20 adicións e 32 borrados
  1. 1 1
      src/hl.h
  2. 9 2
      src/std/cast.c
  3. 9 28
      src/std/obj.c
  4. 1 1
      src/std/types.c

+ 1 - 1
src/hl.h

@@ -613,7 +613,7 @@ HL_API double hl_dyn_castd( void *data, hl_type *t );
 #define hl_invalid_comparison 0xAABBCCDD
 HL_API int hl_dyn_compare( vdynamic *a, vdynamic *b );
 HL_API vdynamic *hl_make_dyn( void *data, hl_type *t );
-HL_API void hl_write_dyn( void *data, hl_type *t, vdynamic *v );
+HL_API void hl_write_dyn( void *data, hl_type *t, vdynamic *v, bool is_tmp );
 
 HL_API void hl_dyn_seti( vdynamic *d, int hfield, hl_type *t, int value );
 HL_API void hl_dyn_setp( vdynamic *d, int hfield, hl_type *t, void *ptr );

+ 9 - 2
src/std/cast.c

@@ -385,7 +385,7 @@ HL_PRIM int hl_dyn_compare( vdynamic *a, vdynamic *b ) {
 	return hl_invalid_comparison;
 }
 
-HL_PRIM void hl_write_dyn( void *data, hl_type *t, vdynamic *v ) {
+HL_PRIM void hl_write_dyn( void *data, hl_type *t, vdynamic *v, bool is_tmp ) {
 	hl_track_call(HL_TRACK_CAST, on_cast(v?v->t:&hlt_dyn,t));
 	switch( t->kind ) {
 	case HUI8:
@@ -407,7 +407,14 @@ HL_PRIM void hl_write_dyn( void *data, hl_type *t, vdynamic *v ) {
 		*(double*)data = hl_dyn_castd(&v,&hlt_dyn);
 		break;
 	default:
-		*(void**)data = hl_dyn_castp(&v,&hlt_dyn,t);
+		{
+			void *ret = (v && hl_same_type(t,v->t)) ? v : hl_dyn_castp(&v,&hlt_dyn,t);
+			if( is_tmp && ret == v ) {
+				ret = hl_alloc_dynamic(v->t);
+				((vdynamic*)ret)->v = v->v;
+			}
+			*(void**)data = ret;
+		}
 		break;
 	}
 }

+ 9 - 28
src/std/obj.c

@@ -923,7 +923,7 @@ HL_PRIM void hl_dyn_seti( vdynamic *d, int hfield, hl_type *t, int value ) {
 			vdynamic tmp;
 			tmp.t = t;
 			tmp.v.i = value;
-			hl_write_dyn(addr,ft,&tmp);
+			hl_write_dyn(addr,ft,&tmp,true);
 		}
 		break;
 	}
@@ -939,7 +939,7 @@ HL_PRIM void hl_dyn_setf( vdynamic *d, int hfield, float value ) {
 		vdynamic tmp;
 		tmp.t = &hlt_f32;
 		tmp.v.f = value;
-		hl_write_dyn(addr,t,&tmp);
+		hl_write_dyn(addr,t,&tmp,true);
 	}
 }
 
@@ -953,7 +953,7 @@ HL_PRIM void hl_dyn_setd( vdynamic *d, int hfield, double value ) {
 		vdynamic tmp;
 		tmp.t = &hlt_f64;
 		tmp.v.d = value;
-		hl_write_dyn(addr,t,&tmp);
+		hl_write_dyn(addr,t,&tmp,true);
 	}
 }
 
@@ -964,12 +964,12 @@ HL_PRIM void hl_dyn_setp( vdynamic *d, int hfield, hl_type *t, void *value ) {
 	if( hl_same_type(t,ft) || (hl_is_ptr(ft) && value == NULL) )
 		*(void**)addr = value;
 	else if( hl_is_dynamic(t) )
-		hl_write_dyn(addr,ft,(vdynamic*)value);
+		hl_write_dyn(addr,ft,(vdynamic*)value,false);
 	else {
 		vdynamic tmp;
 		tmp.t = t;
 		tmp.v.ptr = value;
-		hl_write_dyn(addr,ft,&tmp);
+		hl_write_dyn(addr,ft,&tmp, true);
 	}
 }
 
@@ -994,29 +994,10 @@ HL_PRIM void hl_obj_set_field( vdynamic *obj, int hfield, vdynamic *v ) {
 		hl_dyn_setp(obj,hfield,&hlt_dyn,NULL);
 		return;
 	}
-	switch( v->t->kind ) {
-	case HUI8:
-		hl_dyn_seti(obj,hfield,v->t,v->v.ui8);
-		break;
-	case HUI16:
-		hl_dyn_seti(obj,hfield,v->t,v->v.ui16);
-		break;
-	case HI32:
-		hl_dyn_seti(obj,hfield,v->t,v->v.i);
-		break;
-	case HBOOL:
-		hl_dyn_seti(obj,hfield,v->t,v->v.b);
-		break;
-	case HF32:
-		hl_dyn_setf(obj,hfield,v->v.f);
-		break;
-	case HF64:
-		hl_dyn_setd(obj,hfield,v->v.d);
-		break;
-	default:
-		hl_dyn_setp(obj,hfield,v->t,hl_is_dynamic(v->t)?v:v->v.ptr);
-		break;
-	}
+	hl_track_call(HL_TRACK_DYNFIELD, on_dynfield(obj,hfield));
+	hl_type *ft = NULL;
+	void *addr = hl_obj_lookup_set(obj,hfield,v->t,&ft);
+	hl_write_dyn(addr,ft,v,false);
 }
 
 HL_PRIM bool hl_obj_has_field( vdynamic *obj, int hfield ) {

+ 1 - 1
src/std/types.c

@@ -544,7 +544,7 @@ HL_PRIM venum *hl_alloc_enum_dyn( hl_type *t, int index, varray *args, int nargs
 		return NULL;
 	e = hl_alloc_enum(t, index);
 	for(i=0;i<c->nparams;i++)
-		hl_write_dyn((char*)e+c->offsets[i],c->params[i],hl_aptr(args,vdynamic*)[i]);
+		hl_write_dyn((char*)e+c->offsets[i],c->params[i],hl_aptr(args,vdynamic*)[i],false);
 	return e;
 }