]> Git Repo - secp256k1.git/blobdiff - src/scratch_impl.h
Merge #699: Initialize field elements when resulting in infinity
[secp256k1.git] / src / scratch_impl.h
index 9bd68fe100a31133c6ba09e2b19c344537c46adc..b205620224b6bb339b09ee79e6347e5303aefee3 100644 (file)
@@ -7,71 +7,93 @@
 #ifndef _SECP256K1_SCRATCH_IMPL_H_
 #define _SECP256K1_SCRATCH_IMPL_H_
 
+#include "util.h"
 #include "scratch.h"
 
-/* Using 16 bytes alignment because common architectures never have alignment
- * requirements above 8 for any of the types we care about. In addition we
- * leave some room because currently we don't care about a few bytes.
- * TODO: Determine this at configure time. */
-#define ALIGNMENT 16
-
-static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t init_size, size_t max_size) {
-    secp256k1_scratch* ret = (secp256k1_scratch*)checked_malloc(error_callback, sizeof(*ret));
+static secp256k1_scratch* secp256k1_scratch_create(const secp256k1_callback* error_callback, size_t size) {
+    const size_t base_alloc = ROUND_TO_ALIGN(sizeof(secp256k1_scratch));
+    void *alloc = checked_malloc(error_callback, base_alloc + size);
+    secp256k1_scratch* ret = (secp256k1_scratch *)alloc;
     if (ret != NULL) {
-        ret->data = checked_malloc(error_callback, init_size);
-        if (ret->data == NULL) {
-            free (ret);
-            return NULL;
-        }
-        ret->offset = 0;
-        ret->init_size = init_size;
-        ret->max_size = max_size;
-        ret->error_callback = error_callback;
+        memset(ret, 0, sizeof(*ret));
+        memcpy(ret->magic, "scratch", 8);
+        ret->data = (void *) ((char *) alloc + base_alloc);
+        ret->max_size = size;
     }
     return ret;
 }
 
-static void secp256k1_scratch_destroy(secp256k1_scratch* scratch) {
+static void secp256k1_scratch_destroy(const secp256k1_callback* error_callback, secp256k1_scratch* scratch) {
     if (scratch != NULL) {
-        free(scratch->data);
+        VERIFY_CHECK(scratch->alloc_size == 0); /* all checkpoints should be applied */
+        if (memcmp(scratch->magic, "scratch", 8) != 0) {
+            secp256k1_callback_call(error_callback, "invalid scratch space");
+            return;
+        }
+        memset(scratch->magic, 0, sizeof(scratch->magic));
         free(scratch);
     }
 }
 
-static size_t secp256k1_scratch_max_allocation(const secp256k1_scratch* scratch, size_t objects) {
-    if (scratch->max_size <= objects * ALIGNMENT) {
+static size_t secp256k1_scratch_checkpoint(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch) {
+    if (memcmp(scratch->magic, "scratch", 8) != 0) {
+        secp256k1_callback_call(error_callback, "invalid scratch space");
         return 0;
     }
-    return scratch->max_size - objects * ALIGNMENT;
+    return scratch->alloc_size;
 }
 
-static int secp256k1_scratch_resize(secp256k1_scratch* scratch, size_t n, size_t objects) {
-    n += objects * ALIGNMENT;
-    if (n > scratch->init_size && n <= scratch->max_size) {
-        void *tmp = checked_realloc(scratch->error_callback, scratch->data, n);
-        if (tmp == NULL) {
-            return 0;
-        }
-        scratch->init_size = n;
-        scratch->data = tmp;
+static void secp256k1_scratch_apply_checkpoint(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t checkpoint) {
+    if (memcmp(scratch->magic, "scratch", 8) != 0) {
+        secp256k1_callback_call(error_callback, "invalid scratch space");
+        return;
+    }
+    if (checkpoint > scratch->alloc_size) {
+        secp256k1_callback_call(error_callback, "invalid checkpoint");
+        return;
     }
-    return n <= scratch->max_size;
+    scratch->alloc_size = checkpoint;
 }
 
-static void *secp256k1_scratch_alloc(secp256k1_scratch* scratch, size_t size) {
+static size_t secp256k1_scratch_max_allocation(const secp256k1_callback* error_callback, const secp256k1_scratch* scratch, size_t objects) {
+    if (memcmp(scratch->magic, "scratch", 8) != 0) {
+        secp256k1_callback_call(error_callback, "invalid scratch space");
+        return 0;
+    }
+    /* Ensure that multiplication will not wrap around */
+    if (ALIGNMENT > 1 && objects > SIZE_MAX/(ALIGNMENT - 1)) {
+        return 0;
+    }
+    if (scratch->max_size - scratch->alloc_size <= objects * (ALIGNMENT - 1)) {
+        return 0;
+    }
+    return scratch->max_size - scratch->alloc_size - objects * (ALIGNMENT - 1);
+}
+
+static void *secp256k1_scratch_alloc(const secp256k1_callback* error_callback, secp256k1_scratch* scratch, size_t size) {
     void *ret;
-    size = ((size + ALIGNMENT - 1) / ALIGNMENT) * ALIGNMENT;
-    if (size + scratch->offset > scratch->init_size) {
+    size_t rounded_size;
+
+    rounded_size = ROUND_TO_ALIGN(size);
+    /* Check that rounding did not wrap around */
+    if (rounded_size < size) {
+        return NULL;
+    }
+    size = rounded_size;
+
+    if (memcmp(scratch->magic, "scratch", 8) != 0) {
+        secp256k1_callback_call(error_callback, "invalid scratch space");
         return NULL;
     }
-    ret = (void *) ((unsigned char *) scratch->data + scratch->offset);
+
+    if (size > scratch->max_size - scratch->alloc_size) {
+        return NULL;
+    }
+    ret = (void *) ((char *) scratch->data + scratch->alloc_size);
     memset(ret, 0, size);
-    scratch->offset += size;
-    return ret;
-}
+    scratch->alloc_size += size;
 
-static void secp256k1_scratch_reset(secp256k1_scratch* scratch) {
-    scratch->offset = 0;
+    return ret;
 }
 
 #endif
This page took 0.027192 seconds and 4 git commands to generate.