Browse Source

New test and fixes to crcsync.

Rusty Russell 17 years ago
parent
commit
9fc013b29a
2 changed files with 101 additions and 2 deletions
  1. 8 2
      ccan/crcsync/crcsync.c
  2. 93 0
      ccan/crcsync/test/run-crash.c

+ 8 - 2
ccan/crcsync/crcsync.c

@@ -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);
 	}

+ 93 - 0
ccan/crcsync/test/run-crash.c

@@ -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;
+}