scratch_impl.h (4125B)
1 /*********************************************************************** 2 * Copyright (c) 2017 Andrew Poelstra * 3 * Distributed under the MIT software license, see the accompanying * 4 * file COPYING or https://www.opensource.org/licenses/mit-license.php.* 5 ***********************************************************************/ 6 7 #ifndef SECP256K1_SCRATCH_IMPL_H 8 #define SECP256K1_SCRATCH_IMPL_H 9 10 #include "util.h" 11 #include "scratch.h" 12 13 static haskellsecp256k1_v0_1_0_scratch* haskellsecp256k1_v0_1_0_scratch_create(const haskellsecp256k1_v0_1_0_callback* error_callback, size_t size) { 14 const size_t base_alloc = ROUND_TO_ALIGN(sizeof(haskellsecp256k1_v0_1_0_scratch)); 15 void *alloc = checked_malloc(error_callback, base_alloc + size); 16 haskellsecp256k1_v0_1_0_scratch* ret = (haskellsecp256k1_v0_1_0_scratch *)alloc; 17 if (ret != NULL) { 18 memset(ret, 0, sizeof(*ret)); 19 memcpy(ret->magic, "scratch", 8); 20 ret->data = (void *) ((char *) alloc + base_alloc); 21 ret->max_size = size; 22 } 23 return ret; 24 } 25 26 static void haskellsecp256k1_v0_1_0_scratch_destroy(const haskellsecp256k1_v0_1_0_callback* error_callback, haskellsecp256k1_v0_1_0_scratch* scratch) { 27 if (scratch != NULL) { 28 if (haskellsecp256k1_v0_1_0_memcmp_var(scratch->magic, "scratch", 8) != 0) { 29 haskellsecp256k1_v0_1_0_callback_call(error_callback, "invalid scratch space"); 30 return; 31 } 32 VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */ 33 memset(scratch->magic, 0, sizeof(scratch->magic)); 34 free(scratch); 35 } 36 } 37 38 static size_t haskellsecp256k1_v0_1_0_scratch_checkpoint(const haskellsecp256k1_v0_1_0_callback* error_callback, const haskellsecp256k1_v0_1_0_scratch* scratch) { 39 if (haskellsecp256k1_v0_1_0_memcmp_var(scratch->magic, "scratch", 8) != 0) { 40 haskellsecp256k1_v0_1_0_callback_call(error_callback, "invalid scratch space"); 41 return 0; 42 } 43 return scratch->alloc_size; 44 } 45 46 static void haskellsecp256k1_v0_1_0_scratch_apply_checkpoint(const haskellsecp256k1_v0_1_0_callback* error_callback, haskellsecp256k1_v0_1_0_scratch* scratch, size_t checkpoint) { 47 if (haskellsecp256k1_v0_1_0_memcmp_var(scratch->magic, "scratch", 8) != 0) { 48 haskellsecp256k1_v0_1_0_callback_call(error_callback, "invalid scratch space"); 49 return; 50 } 51 if (checkpoint > scratch->alloc_size) { 52 haskellsecp256k1_v0_1_0_callback_call(error_callback, "invalid checkpoint"); 53 return; 54 } 55 scratch->alloc_size = checkpoint; 56 } 57 58 static size_t haskellsecp256k1_v0_1_0_scratch_max_allocation(const haskellsecp256k1_v0_1_0_callback* error_callback, const haskellsecp256k1_v0_1_0_scratch* scratch, size_t objects) { 59 if (haskellsecp256k1_v0_1_0_memcmp_var(scratch->magic, "scratch", 8) != 0) { 60 haskellsecp256k1_v0_1_0_callback_call(error_callback, "invalid scratch space"); 61 return 0; 62 } 63 /* Ensure that multiplication will not wrap around */ 64 if (ALIGNMENT > 1 && objects > SIZE_MAX/(ALIGNMENT - 1)) { 65 return 0; 66 } 67 if (scratch->max_size - scratch->alloc_size <= objects * (ALIGNMENT - 1)) { 68 return 0; 69 } 70 return scratch->max_size - scratch->alloc_size - objects * (ALIGNMENT - 1); 71 } 72 73 static void *haskellsecp256k1_v0_1_0_scratch_alloc(const haskellsecp256k1_v0_1_0_callback* error_callback, haskellsecp256k1_v0_1_0_scratch* scratch, size_t size) { 74 void *ret; 75 size_t rounded_size; 76 77 rounded_size = ROUND_TO_ALIGN(size); 78 /* Check that rounding did not wrap around */ 79 if (rounded_size < size) { 80 return NULL; 81 } 82 size = rounded_size; 83 84 if (haskellsecp256k1_v0_1_0_memcmp_var(scratch->magic, "scratch", 8) != 0) { 85 haskellsecp256k1_v0_1_0_callback_call(error_callback, "invalid scratch space"); 86 return NULL; 87 } 88 89 if (size > scratch->max_size - scratch->alloc_size) { 90 return NULL; 91 } 92 ret = (void *) ((char *) scratch->data + scratch->alloc_size); 93 memset(ret, 0, size); 94 scratch->alloc_size += size; 95 96 return ret; 97 } 98 99 #endif