New test and fixes to crcsync.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 31 Mar 2009 05:18:59 +0000 (15:48 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 31 Mar 2009 05:18:59 +0000 (15:48 +1030)
ccan/crcsync/crcsync.c
ccan/crcsync/test/run-crash.c [new file with mode: 0644]

index 87f513ea90cc74576b2f5854ccd68431f8ed5e65..2301bc103c1fce4952dbb14cd88057416d62339c 100644 (file)
@@ -192,7 +192,11 @@ size_t crc_read_block(struct crc_context *ctx, long *result,
                if (ctx->literal_bytes > ctx->block_size) {
                        *result = ctx->literal_bytes - ctx->block_size;
                        ctx->literal_bytes -= *result;
-                       ctx->buffer_start += *result;
+                       /* Advance buffer. */
+                       if (*result >= buffer_size(ctx))
+                               ctx->buffer_start = ctx->buffer_end = 0;
+                       else
+                               ctx->buffer_start += *result;
                } else
                        *result = 0;
 
@@ -206,7 +210,9 @@ size_t crc_read_block(struct crc_context *ctx, long *result,
                        ctx->buffer_end -= ctx->buffer_start;
                        ctx->buffer_start = 0;
                }
-               memcpy(ctx->buffer + ctx->buffer_end, buf, len);
+
+               /* Copy len bytes from tail of buffer. */
+               memcpy(ctx->buffer + ctx->buffer_end, buf + buflen - len, len);
                ctx->buffer_end += len;
                assert(buffer_size(ctx) <= ctx->block_size);
        }
diff --git a/ccan/crcsync/test/run-crash.c b/ccan/crcsync/test/run-crash.c
new file mode 100644 (file)
index 0000000..c047cce
--- /dev/null
@@ -0,0 +1,93 @@
+/* This used to crash us on 64-bit; submitted by
+   Alex Wulms <alex.wulms@scarlet.be> */
+#include "crcsync/crcsync.h"
+#include "crcsync/crcsync.c"
+#include "tap/tap.h"
+#include <stdlib.h>
+#include <stdbool.h>
+
+/* FIXME: ccanize. */
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+typedef struct {
+       int block_count;
+       unsigned int *crcs;
+} crc_info_t;
+
+static void crcblocks(crc_info_t *crc_info, char *data, int datalen, int blocksize)
+{
+       crc_info->block_count = (datalen+blocksize-1)/blocksize;
+       crc_info->crcs = malloc(sizeof(unsigned int)*(crc_info->block_count + 1));
+       crc_of_blocks(data, datalen, blocksize, 30, crc_info->crcs);
+}
+
+#define BLOCKSIZE 5
+
+int main(int argc, char *argv[])
+{
+       /* Divided into BLOCKSIZE blocks */
+       char *data1 =
+               "abcde" "fghij" "klmno" "pqrst" "uvwxy" "z ABC"
+               "DEFGH" "IJKLM" "NOPQR" "STUVW" "XYZ 0" "12345" "6789";
+       /* Divided into blocks that match. */
+       char *data2 =
+               /* NO MATCH */
+               "acde"
+               /* MATCH */
+               "fghij" "klmno" 
+               /* NO MATCH */
+               "pqr-a-very-long-test-that-differs-between-two-invokations-of-the-same-page-st"
+               /* MATCH */
+               "uvwxy" "z ABC" "DEFGH" "IJKLM" "NOPQR" "STUVW" "XYZ 0" "12345"
+               /* NO MATCH */
+               "6789ab";
+
+       int expected[] = { 4,
+                          -2, -3,
+                          77,
+                          -5, -6, -7, -8, -9, -10, -11, -12,
+                          6 };
+       crc_info_t crc_info1;
+       struct crc_context *crcctx;
+       long result;
+       size_t ndigested;
+       size_t offset = 0;
+       size_t len2 = strlen(data2);
+       int expected_i = 0;
+
+       plan_tests(ARRAY_SIZE(expected) + 2);
+       crcblocks(&crc_info1, data1, strlen(data1), BLOCKSIZE);
+
+       crcctx = crc_context_new(BLOCKSIZE, 30, crc_info1.crcs, crc_info1.block_count);
+       while ( offset < len2)
+       {
+               ndigested = crc_read_block(crcctx, &result, data2+offset, len2 - offset);
+               offset += ndigested;
+               if (result < 0)
+                       /* Match. */
+                       ok1(result == expected[expected_i++]);
+               else {
+                       /* Literal. */
+                       ok1(result <= expected[expected_i]);
+                       expected[expected_i] -= result;
+                       if (!expected[expected_i])
+                               expected_i++;
+               }
+       }
+
+       while ((result = crc_read_flush(crcctx)) != 0) {
+               if (result < 0)
+                       /* Match. */
+                       ok1(result == expected[expected_i++]);
+               else {
+                       /* Literal. */
+                       ok1(result <= expected[expected_i]);
+                       expected[expected_i] -= result;
+                       if (!expected[expected_i])
+                               expected_i++;
+               }
+       }
+       ok1(expected_i == ARRAY_SIZE(expected));
+       
+       return 0;
+}