Pārlūkot izejas kodu

Bugfix in __getstate__

After mutation some token has non zero initialized useless data that should not
be copied in state.
Yann Weber 9 mēnešus atpakaļ
vecāks
revīzija
866987dcf0
2 mainītis faili ar 28 papildinājumiem un 10 dzēšanām
  1. 27
    10
      python_rpnexpr.c
  2. 1
    0
      tests/tests_rpn_copy.py

+ 27
- 10
python_rpnexpr.c Parādīt failu

@@ -273,6 +273,7 @@ PyObject* rpnexpr_getstate(PyObject *self, PyObject *noargs)
273 273
 	total_sz += expr_self->rpn->toks.tokens_sz * sizeof(rpn_token_t);
274 274
 	total_sz += expr_self->rpn->stack_sz * sizeof(rpn_value_t);
275 275
 
276
+	bzero(&resbuf, sizeof(resbuf));
276 277
 	resbuf.total_sz = total_sz;
277 278
 	resbuf.argc = expr_self->rpn->args_count;
278 279
 	resbuf.stack_sz = expr_self->rpn->stack_sz;
@@ -298,23 +299,39 @@ PyObject* rpnexpr_getstate(PyObject *self, PyObject *noargs)
298 299
 	}
299 300
 	if(resbuf.token_sz)
300 301
 	{
301
-		for(i=0; i<expr_self->rpn->toks.tokens_sz;i++)
302
+		/**@todo can lead to stack overflow on huge expressions ? */
303
+		rpn_token_t tokens[resbuf.token_sz];
304
+		bzero(tokens, sizeof(rpn_token_t) * resbuf.token_sz);
305
+
306
+		for(i=0; i<expr_self->rpn->toks.tokens_sz; i++)
302 307
 		{
303
-			// restore op pointers
304
-			expr_self->rpn->toks.tokens[i].op = NULL;
308
+			const rpn_token_t *cur = &expr_self->rpn->toks.tokens[i];
309
+			tokens[i].type = cur->type;
310
+			switch(tokens[i].type)
311
+			{
312
+				case RPN_op:
313
+					tokens[i].op_n = cur->op_n;
314
+					tokens[i].op = NULL;
315
+					break;
316
+				case RPN_arg:
317
+					tokens[i].arg_n = cur->arg_n;
318
+					break;
319
+				case RPN_val:
320
+					tokens[i].value = cur->value;
321
+					break;
322
+				default:
323
+					PyErr_SetString(PyExc_RuntimeError,
324
+							"__getstate__ invalid token");
325
+					return NULL;
326
+			}
305 327
 		}
306
-	
328
+
307 329
 		if(!(part=PyBytes_FromStringAndSize(
308
-				(char*)expr_self->rpn->toks.tokens,
330
+				(char*)tokens,
309 331
 				sizeof(rpn_token_t) * resbuf.token_sz)))
310 332
 		{
311 333
 			return NULL;
312 334
 		}
313
-		for(i=0; i<expr_self->rpn->toks.tokens_sz;i++)
314
-		{
315
-			// restore op pointers
316
-			expr_self->rpn->toks.tokens[i].op = &(rpn_ops[expr_self->rpn->toks.tokens[i].op_n]);
317
-		}
318 335
 	
319 336
 		PyBytes_ConcatAndDel(&res, part);
320 337
 		if(!res)

+ 1
- 0
tests/tests_rpn_copy.py Parādīt failu

@@ -69,6 +69,7 @@ class TestRpnExprState(unittest.TestCase):
69 69
                          msg="EXPR: %r != %r (%r != %r)" % (e, e2, ds_e, ds_e2))
70 70
         for i in range(100):
71 71
             e = pyrpn.RPNExpr(pyrpn.random_expr(0), 2)
72
+            e.mutate(n_mutations=15);
72 73
 
73 74
             e2 = pickle.loads(pickle.dumps(e))
74 75
 

Notiek ielāde…
Atcelt
Saglabāt