@@ -333,7 +333,11 @@ void run_context_tests(int use_prealloc) {
333333}
334334
335335void run_scratch_tests (void ) {
336+ const size_t adj_alloc = ((500 + ALIGNMENT - 1 ) / ALIGNMENT ) * ALIGNMENT ;
337+
336338 int32_t ecount = 0 ;
339+ size_t checkpoint ;
340+ size_t checkpoint_2 ;
337341 secp256k1_context * none = secp256k1_context_create (SECP256K1_CONTEXT_NONE );
338342 secp256k1_scratch_space * scratch ;
339343 secp256k1_scratch_space local_scratch ;
@@ -348,43 +352,54 @@ void run_scratch_tests(void) {
348352
349353 /* Test internal API */
350354 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 );
356358
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 );
360361 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 );
364366
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 */
368368 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 );
369380
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 );
372384 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 );
373389
374390 /* try to use badly initialized scratch space */
375391 memset (& local_scratch , 0 , sizeof (local_scratch ));
376392 scratch = & local_scratch ;
377393 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 );
382394 CHECK (ecount == 3 );
383- secp256k1_scratch_deallocate_frame ( & none -> error_callback , scratch );
395+ CHECK ( secp256k1_scratch_alloc ( & none -> error_callback , scratch , 500 ) == NULL );
384396 CHECK (ecount == 4 );
385397 secp256k1_scratch_space_destroy (none , scratch );
386398 CHECK (ecount == 5 );
387399
400+ /* cleanup */
401+ secp256k1_scratch_space_destroy (none , scratch );
402+ secp256k1_scratch_space_destroy (none , NULL ); /* no-op */
388403 secp256k1_context_destroy (none );
389404}
390405
@@ -2946,16 +2961,26 @@ void test_ecmult_multi_pippenger_max_points(void) {
29462961 int bucket_window = 0 ;
29472962
29482963 for (; scratch_size < max_size ; scratch_size += 256 ) {
2964+ size_t i ;
2965+ size_t total_alloc ;
2966+ size_t checkpoint ;
29492967 scratch = secp256k1_scratch_create (& ctx -> error_callback , scratch_size );
29502968 CHECK (scratch != NULL );
2969+ checkpoint = secp256k1_scratch_checkpoint (& ctx -> error_callback , scratch );
29512970 n_points_supported = secp256k1_pippenger_max_points (& ctx -> error_callback , scratch );
29522971 if (n_points_supported == 0 ) {
29532972 secp256k1_scratch_destroy (& ctx -> error_callback , scratch );
29542973 continue ;
29552974 }
29562975 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 );
29592984 secp256k1_scratch_destroy (& ctx -> error_callback , scratch );
29602985 }
29612986 CHECK (bucket_window == PIPPENGER_MAX_BUCKET_WINDOW );
0 commit comments