@@ -333,7 +333,11 @@ void run_context_tests(int use_prealloc) {
333
333
}
334
334
335
335
void run_scratch_tests (void ) {
336
+ const size_t adj_alloc = ((500 + ALIGNMENT - 1 ) / ALIGNMENT ) * ALIGNMENT ;
337
+
336
338
int32_t ecount = 0 ;
339
+ size_t checkpoint ;
340
+ size_t checkpoint_2 ;
337
341
secp256k1_context * none = secp256k1_context_create (SECP256K1_CONTEXT_NONE );
338
342
secp256k1_scratch_space * scratch ;
339
343
secp256k1_scratch_space local_scratch ;
@@ -348,43 +352,54 @@ void run_scratch_tests(void) {
348
352
349
353
/* Test internal API */
350
354
CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ) == 1000 );
351
- CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 1 ) < 1000 );
352
-
353
- /* Allocating 500 bytes with no frame fails */
354
- CHECK (secp256k1_scratch_alloc (& none -> error_callback , scratch , 500 ) == NULL );
355
- CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ) == 1000 );
355
+ CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 1 ) == 1000 - (ALIGNMENT - 1 ));
356
+ CHECK (scratch -> alloc_size == 0 );
357
+ CHECK (scratch -> alloc_size % ALIGNMENT == 0 );
356
358
357
- /* ...but pushing a new stack frame does affect the max allocation */
358
- CHECK (secp256k1_scratch_allocate_frame (& none -> error_callback , scratch , 500 , 1 ) == 1 );
359
- CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 1 ) < 500 ); /* 500 - (ALIGNMENT - 1) */
359
+ /* Allocating 500 bytes succeeds */
360
+ checkpoint = secp256k1_scratch_checkpoint (& none -> error_callback , scratch );
360
361
CHECK (secp256k1_scratch_alloc (& none -> error_callback , scratch , 500 ) != NULL );
361
- CHECK (secp256k1_scratch_alloc (& none -> error_callback , scratch , 500 ) == NULL );
362
-
363
- CHECK (secp256k1_scratch_allocate_frame (& none -> error_callback , scratch , 500 , 1 ) == 0 );
362
+ CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ) == 1000 - adj_alloc );
363
+ CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 1 ) == 1000 - adj_alloc - (ALIGNMENT - 1 ));
364
+ CHECK (scratch -> alloc_size != 0 );
365
+ CHECK (scratch -> alloc_size % ALIGNMENT == 0 );
364
366
365
- /* ...and this effect is undone by popping the frame */
366
- secp256k1_scratch_deallocate_frame (& none -> error_callback , scratch );
367
- CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ) == 1000 );
367
+ /* Allocating another 500 bytes fails */
368
368
CHECK (secp256k1_scratch_alloc (& none -> error_callback , scratch , 500 ) == NULL );
369
+ CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ) == 1000 - adj_alloc );
370
+ CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 1 ) == 1000 - adj_alloc - (ALIGNMENT - 1 ));
371
+ CHECK (scratch -> alloc_size != 0 );
372
+ CHECK (scratch -> alloc_size % ALIGNMENT == 0 );
373
+
374
+ /* ...but it succeeds once we apply the checkpoint to undo it */
375
+ secp256k1_scratch_apply_checkpoint (& none -> error_callback , scratch , checkpoint );
376
+ CHECK (scratch -> alloc_size == 0 );
377
+ CHECK (secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ) == 1000 );
378
+ CHECK (secp256k1_scratch_alloc (& none -> error_callback , scratch , 500 ) != NULL );
379
+ CHECK (scratch -> alloc_size != 0 );
369
380
370
- /* cleanup */
371
- secp256k1_scratch_space_destroy (none , scratch );
381
+ /* try to apply a bad checkpoint */
382
+ checkpoint_2 = secp256k1_scratch_checkpoint (& none -> error_callback , scratch );
383
+ secp256k1_scratch_apply_checkpoint (& none -> error_callback , scratch , checkpoint );
372
384
CHECK (ecount == 0 );
385
+ secp256k1_scratch_apply_checkpoint (& none -> error_callback , scratch , checkpoint_2 ); /* checkpoint_2 is after checkpoint */
386
+ CHECK (ecount == 1 );
387
+ secp256k1_scratch_apply_checkpoint (& none -> error_callback , scratch , (size_t ) -1 ); /* this is just wildly invalid */
388
+ CHECK (ecount == 2 );
373
389
374
390
/* try to use badly initialized scratch space */
391
+ secp256k1_scratch_space_destroy (none , scratch );
375
392
memset (& local_scratch , 0 , sizeof (local_scratch ));
376
393
scratch = & local_scratch ;
377
394
CHECK (!secp256k1_scratch_max_allocation (& none -> error_callback , scratch , 0 ));
378
- CHECK (ecount == 1 );
379
- CHECK (secp256k1_scratch_allocate_frame (& none -> error_callback , scratch , 500 , 1 ) == 0 );
380
- CHECK (ecount == 2 );
381
- CHECK (secp256k1_scratch_alloc (& none -> error_callback , scratch , 500 ) == NULL );
382
395
CHECK (ecount == 3 );
383
- secp256k1_scratch_deallocate_frame ( & none -> error_callback , scratch );
396
+ CHECK ( secp256k1_scratch_alloc ( & none -> error_callback , scratch , 500 ) == NULL );
384
397
CHECK (ecount == 4 );
385
398
secp256k1_scratch_space_destroy (none , scratch );
386
399
CHECK (ecount == 5 );
387
400
401
+ /* cleanup */
402
+ secp256k1_scratch_space_destroy (none , NULL ); /* no-op */
388
403
secp256k1_context_destroy (none );
389
404
}
390
405
@@ -2946,16 +2961,26 @@ void test_ecmult_multi_pippenger_max_points(void) {
2946
2961
int bucket_window = 0 ;
2947
2962
2948
2963
for (; scratch_size < max_size ; scratch_size += 256 ) {
2964
+ size_t i ;
2965
+ size_t total_alloc ;
2966
+ size_t checkpoint ;
2949
2967
scratch = secp256k1_scratch_create (& ctx -> error_callback , scratch_size );
2950
2968
CHECK (scratch != NULL );
2969
+ checkpoint = secp256k1_scratch_checkpoint (& ctx -> error_callback , scratch );
2951
2970
n_points_supported = secp256k1_pippenger_max_points (& ctx -> error_callback , scratch );
2952
2971
if (n_points_supported == 0 ) {
2953
2972
secp256k1_scratch_destroy (& ctx -> error_callback , scratch );
2954
2973
continue ;
2955
2974
}
2956
2975
bucket_window = secp256k1_pippenger_bucket_window (n_points_supported );
2957
- CHECK (secp256k1_scratch_allocate_frame (& ctx -> error_callback , scratch , secp256k1_pippenger_scratch_size (n_points_supported , bucket_window ), PIPPENGER_SCRATCH_OBJECTS ));
2958
- secp256k1_scratch_deallocate_frame (& ctx -> error_callback , scratch );
2976
+ /* allocate `total_alloc` bytes over `PIPPENGER_SCRATCH_OBJECTS` many allocations */
2977
+ total_alloc = secp256k1_pippenger_scratch_size (n_points_supported , bucket_window );
2978
+ for (i = 0 ; i < PIPPENGER_SCRATCH_OBJECTS - 1 ; i ++ ) {
2979
+ CHECK (secp256k1_scratch_alloc (& ctx -> error_callback , scratch , 1 ));
2980
+ total_alloc -- ;
2981
+ }
2982
+ CHECK (secp256k1_scratch_alloc (& ctx -> error_callback , scratch , total_alloc ));
2983
+ secp256k1_scratch_apply_checkpoint (& ctx -> error_callback , scratch , checkpoint );
2959
2984
secp256k1_scratch_destroy (& ctx -> error_callback , scratch );
2960
2985
}
2961
2986
CHECK (bucket_window == PIPPENGER_MAX_BUCKET_WINDOW );
0 commit comments