Browse code

shared/cdiff.c: scripts can now control size of input buffer (bb#1395)

git-svn: trunk@4837

Tomasz Kojm authored on 2009/02/19 20:56:27
Showing 2 changed files
... ...
@@ -1,3 +1,7 @@
1
+Thu Feb 19 13:28:04 CET 2009 (tk)
2
+---------------------------------
3
+ * shared/cdiff.c: scripts can now control size of input buffer (bb#1395)
4
+
1 5
 Thu Feb 19 11:20:58 EET 2009 (edwin)
2 6
 ------------------------------------
3 7
  * clamd/, etc/, libclamav/, unit_tests/: fix distcheck.
... ...
@@ -51,6 +51,9 @@
51 51
 #define PSS_NBITS 2048
52 52
 #define PSS_DIGEST_LENGTH 32
53 53
 
54
+/* the line size can be changed from within .cdiff */
55
+#define CDIFF_LINE_SIZE CLI_DEFAULT_LSIG_BUFSIZE + 32
56
+
54 57
 struct cdiff_node {
55 58
     unsigned int lineno;
56 59
     char *str, *str2;
... ...
@@ -67,16 +70,16 @@ struct cdiff_ctx {
67 67
 struct cdiff_cmd {
68 68
     const char *name;
69 69
     unsigned short argc;
70
-    int (*handler)(const char *, struct cdiff_ctx *);
70
+    int (*handler)(const char *, struct cdiff_ctx *, char *, unsigned int);
71 71
 };
72 72
 
73
-static int cdiff_cmd_open(const char *cmdstr, struct cdiff_ctx *ctx);
74
-static int cdiff_cmd_add(const char *cmdstr, struct cdiff_ctx *ctx);
75
-static int cdiff_cmd_del(const char *cmdstr, struct cdiff_ctx *ctx);
76
-static int cdiff_cmd_xchg(const char *cmdstr, struct cdiff_ctx *ctx);
77
-static int cdiff_cmd_close(const char *cmdstr, struct cdiff_ctx *ctx);
78
-static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx);
79
-static int cdiff_cmd_unlink(const char *cmdstr, struct cdiff_ctx *ctx);
73
+static int cdiff_cmd_open(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
74
+static int cdiff_cmd_add(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
75
+static int cdiff_cmd_del(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
76
+static int cdiff_cmd_xchg(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
77
+static int cdiff_cmd_close(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
78
+static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
79
+static int cdiff_cmd_unlink(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen);
80 80
 
81 81
 static struct cdiff_cmd commands[] = {
82 82
     /* OPEN db_name */
... ...
@@ -170,7 +173,7 @@ static char *cdiff_token(const char *line, unsigned int token, unsigned int last
170 170
     return buffer;
171 171
 }
172 172
 
173
-static int cdiff_cmd_open(const char *cmdstr, struct cdiff_ctx *ctx)
173
+static int cdiff_cmd_open(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
174 174
 {
175 175
 	char *db;
176 176
 	unsigned int i;
... ...
@@ -199,7 +202,7 @@ static int cdiff_cmd_open(const char *cmdstr, struct cdiff_ctx *ctx)
199 199
     return 0;
200 200
 }
201 201
 
202
-static int cdiff_cmd_add(const char *cmdstr, struct cdiff_ctx *ctx)
202
+static int cdiff_cmd_add(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
203 203
 {
204 204
 	char *sig;
205 205
 	struct cdiff_node *new;
... ...
@@ -228,7 +231,7 @@ static int cdiff_cmd_add(const char *cmdstr, struct cdiff_ctx *ctx)
228 228
     return 0;
229 229
 }
230 230
 
231
-static int cdiff_cmd_del(const char *cmdstr, struct cdiff_ctx *ctx)
231
+static int cdiff_cmd_del(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
232 232
 {
233 233
 	char *arg;
234 234
 	struct cdiff_node *pt, *last, *new;
... ...
@@ -285,7 +288,7 @@ static int cdiff_cmd_del(const char *cmdstr, struct cdiff_ctx *ctx)
285 285
     return 0;
286 286
 }
287 287
 
288
-static int cdiff_cmd_xchg(const char *cmdstr, struct cdiff_ctx *ctx)
288
+static int cdiff_cmd_xchg(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
289 289
 {
290 290
 	char *arg, *arg2;
291 291
 	struct cdiff_node *pt, *last, *new;
... ...
@@ -350,11 +353,11 @@ static int cdiff_cmd_xchg(const char *cmdstr, struct cdiff_ctx *ctx)
350 350
     return 0;
351 351
 }
352 352
 
353
-static int cdiff_cmd_close(const char *cmdstr, struct cdiff_ctx *ctx)
353
+static int cdiff_cmd_close(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
354 354
 {
355 355
 	struct cdiff_node *add, *del, *xchg;
356 356
 	unsigned int lines = 0;
357
-	char *tmp, line[CLI_DEFAULT_LSIG_BUFSIZE + 32];
357
+	char *tmp;
358 358
 	FILE *fh, *tmpfh;
359 359
 
360 360
 
... ...
@@ -387,11 +390,11 @@ static int cdiff_cmd_close(const char *cmdstr, struct cdiff_ctx *ctx)
387 387
 	    return -1;
388 388
 	}
389 389
 
390
-	while(fgets(line, sizeof(line), fh)) {
390
+	while(fgets(lbuf, lbuflen, fh)) {
391 391
 	    lines++;
392 392
 
393 393
 	    if(del && del->lineno == lines) {
394
-		if(strncmp(line, del->str, strlen(del->str))) {
394
+		if(strncmp(lbuf, del->str, strlen(del->str))) {
395 395
 		    fclose(fh);
396 396
 		    fclose(tmpfh);
397 397
 		    unlink(tmp);
... ...
@@ -399,13 +402,12 @@ static int cdiff_cmd_close(const char *cmdstr, struct cdiff_ctx *ctx)
399 399
 		    logg("!cdiff_cmd_close: Can't apply DEL at line %d of %s\n", lines, ctx->open_db);
400 400
 		    return -1;
401 401
 		}
402
-
403 402
 		del = del->next;
404 403
 		continue;
405 404
 	    }
406 405
 
407 406
 	    if(xchg && xchg->lineno == lines) {
408
-		if(strncmp(line, xchg->str, strlen(xchg->str))) {
407
+		if(strncmp(lbuf, xchg->str, strlen(xchg->str))) {
409 408
 		    fclose(fh);
410 409
 		    fclose(tmpfh);
411 410
 		    unlink(tmp);
... ...
@@ -426,7 +428,7 @@ static int cdiff_cmd_close(const char *cmdstr, struct cdiff_ctx *ctx)
426 426
 		continue;
427 427
 	    }
428 428
 
429
-	    if(fputs(line, tmpfh) == EOF) {
429
+	    if(fputs(lbuf, tmpfh) == EOF) {
430 430
 		fclose(fh);
431 431
 		fclose(tmpfh);
432 432
 		unlink(tmp);
... ...
@@ -487,10 +489,10 @@ static int cdiff_cmd_close(const char *cmdstr, struct cdiff_ctx *ctx)
487 487
     return 0;
488 488
 }
489 489
 
490
-static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx)
490
+static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
491 491
 {
492 492
 	unsigned int lines = 0, start_line, end_line;
493
-	char *arg, *srcdb, *dstdb, *tmpdb, line[CLI_DEFAULT_LSIG_BUFSIZE + 32], *start_str, *end_str;
493
+	char *arg, *srcdb, *dstdb, *tmpdb, *start_str, *end_str;
494 494
 	FILE *src, *dst, *tmp;
495 495
 
496 496
 
... ...
@@ -586,11 +588,11 @@ static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx)
586 586
 	return -1;
587 587
     }
588 588
 
589
-    while(fgets(line, sizeof(line), src)) {
589
+    while(fgets(lbuf, lbuflen, src)) {
590 590
 	lines++;
591 591
 
592 592
 	if(lines == start_line) {
593
-	    if(strncmp(line, start_str, strlen(start_str))) {
593
+	    if(strncmp(lbuf, start_str, strlen(start_str))) {
594 594
 		free(start_str);
595 595
 		free(end_str);
596 596
 		free(srcdb);
... ...
@@ -605,7 +607,7 @@ static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx)
605 605
 	    }
606 606
 
607 607
 	    do {
608
-		if(fputs(line, dst) == EOF) {
608
+		if(fputs(lbuf, dst) == EOF) {
609 609
 		    free(start_str);
610 610
 		    free(end_str);
611 611
 		    free(srcdb);
... ...
@@ -618,14 +620,14 @@ static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx)
618 618
 		    free(dstdb);
619 619
 		    return -1;
620 620
 		}
621
-	    } while((lines < end_line) && fgets(line, sizeof(line), src) && lines++);
621
+	    } while((lines < end_line) && fgets(lbuf, lbuflen, src) && lines++);
622 622
 
623 623
 	    fclose(dst);
624 624
 	    free(dstdb);
625 625
 	    dstdb = NULL;
626 626
 	    free(start_str);
627 627
 
628
-	    if(strncmp(line, end_str, strlen(end_str))) {
628
+	    if(strncmp(lbuf, end_str, strlen(end_str))) {
629 629
 		free(end_str);
630 630
 		free(srcdb);
631 631
 		fclose(src);
... ...
@@ -640,7 +642,7 @@ static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx)
640 640
 	    continue;
641 641
 	}
642 642
 
643
-	if(fputs(line, tmp) == EOF) {
643
+	if(fputs(lbuf, tmp) == EOF) {
644 644
 	    free(srcdb);
645 645
 	    fclose(src);
646 646
 	    fclose(tmp);
... ...
@@ -688,7 +690,7 @@ static int cdiff_cmd_move(const char *cmdstr, struct cdiff_ctx *ctx)
688 688
     return 0;
689 689
 }
690 690
 
691
-static int cdiff_cmd_unlink(const char *cmdstr, struct cdiff_ctx *ctx)
691
+static int cdiff_cmd_unlink(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
692 692
 {
693 693
 	char *db;
694 694
 	unsigned int i;
... ...
@@ -722,10 +724,10 @@ static int cdiff_cmd_unlink(const char *cmdstr, struct cdiff_ctx *ctx)
722 722
     return 0;
723 723
 }
724 724
 
725
-static int cdiff_execute(const char *cmdstr, struct cdiff_ctx *ctx)
725
+static int cdiff_execute(const char *cmdstr, struct cdiff_ctx *ctx, char *lbuf, unsigned int lbuflen)
726 726
 {
727 727
 	char *cmd_name, *tmp;
728
-	int (*cmd_handler)(const char *, struct cdiff_ctx *) = NULL;
728
+	int (*cmd_handler)(const char *, struct cdiff_ctx *, char *, unsigned int) = NULL;
729 729
 	unsigned int i;
730 730
 
731 731
 
... ...
@@ -755,7 +757,7 @@ static int cdiff_execute(const char *cmdstr, struct cdiff_ctx *ctx)
755 755
     }
756 756
     free(tmp);
757 757
 
758
-    if(cmd_handler(cmdstr, ctx)) {
758
+    if(cmd_handler(cmdstr, ctx, lbuf, lbuflen)) {
759 759
 	logg("!cdiff_apply: Can't execute command %s\n", cmd_name);
760 760
 	free(cmd_name);
761 761
 	return -1;
... ...
@@ -866,9 +868,9 @@ int cdiff_apply(int fd, unsigned short mode)
866 866
 	struct cdiff_ctx ctx;
867 867
 	FILE *fh;
868 868
 	gzFile *gzh;
869
-	char line[CLI_DEFAULT_LSIG_BUFSIZE + 32], buff[FILEBUFF], *dsig = NULL;
869
+	char *line, *lbuf, buff[FILEBUFF], *dsig = NULL;
870 870
 	unsigned int lines = 0, cmds = 0;
871
-	unsigned int difflen, diffremain;
871
+	unsigned int difflen, diffremain, line_size = CDIFF_LINE_SIZE;
872 872
 	int end, i, n;
873 873
 	struct stat sb;
874 874
 	int desc;
... ...
@@ -884,18 +886,35 @@ int cdiff_apply(int fd, unsigned short mode)
884 884
 	return -1;
885 885
     }
886 886
 
887
+    if(!(line = malloc(line_size))) {
888
+	logg("!cdiff_apply: Can't allocate memory for 'line'\n");
889
+	close(desc);
890
+	return -1;
891
+    }
892
+
893
+    if(!(lbuf = malloc(line_size))) {
894
+	logg("!cdiff_apply: Can't allocate memory for 'lbuf'\n");
895
+	close(desc);
896
+	free(line);
897
+	return -1;
898
+    }
899
+
887 900
     if(mode == 1) { /* .cdiff */
888 901
 
889 902
 	if(lseek(desc, -DSIGBUFF, SEEK_END) == -1) {
890 903
 	    logg("!cdiff_apply: lseek(desc, %d, SEEK_END) failed\n", -DSIGBUFF);
891 904
 	    close(desc);
905
+	    free(line);
906
+	    free(lbuf);
892 907
 	    return -1;
893 908
 	}
894 909
 
895
-	memset(line, 0, sizeof(line));
910
+	memset(line, 0, line_size);
896 911
 	if(read(desc, line, DSIGBUFF) != DSIGBUFF) {
897 912
 	    logg("!cdiff_apply: Can't read %d bytes\n", DSIGBUFF);
898 913
 	    close(desc);
914
+	    free(line);
915
+	    free(lbuf);
899 916
 	    return -1;
900 917
 	}
901 918
 
... ...
@@ -909,12 +928,16 @@ int cdiff_apply(int fd, unsigned short mode)
909 909
 	if(!dsig) {
910 910
 	    logg("!cdiff_apply: No digital signature in cdiff file\n");
911 911
 	    close(desc);
912
+	    free(line);
913
+	    free(lbuf);
912 914
 	    return -1;
913 915
 	}
914 916
 
915 917
 	if(fstat(desc, &sb) == -1) {
916 918
 	    logg("!cdiff_apply: Can't fstat file\n");
917 919
 	    close(desc);
920
+	    free(line);
921
+	    free(lbuf);
918 922
 	    return -1;
919 923
 	}
920 924
 
... ...
@@ -922,12 +945,16 @@ int cdiff_apply(int fd, unsigned short mode)
922 922
 	if(end < 0) {
923 923
 	    logg("!cdiff_apply: compressed data end offset < 0\n");
924 924
 	    close(desc);
925
+	    free(line);
926
+	    free(lbuf);
925 927
 	    return -1;
926 928
 	}
927 929
 
928 930
 	if(lseek(desc, 0, SEEK_SET) == -1) {
929 931
 	    logg("!cdiff_apply: lseek(desc, 0, SEEK_SET) failed\n");
930 932
 	    close(desc);
933
+	    free(line);
934
+	    free(lbuf);
931 935
 	    return -1;
932 936
 	}
933 937
 
... ...
@@ -947,12 +974,16 @@ int cdiff_apply(int fd, unsigned short mode)
947 947
 	if(pss_versig(digest, dsig)) {
948 948
 	    logg("!cdiff_apply: Incorrect digital signature\n");
949 949
 	    close(desc);
950
+	    free(line);
951
+	    free(lbuf);
950 952
 	    return -1;
951 953
 	}
952 954
 
953 955
 	if(lseek(desc, 0, SEEK_SET) == -1) {
954 956
 	    logg("!cdiff_apply: lseek(desc, 0, SEEK_SET) failed\n");
955 957
 	    close(desc);
958
+	    free(line);
959
+	    free(lbuf);
956 960
 	    return -1;
957 961
 	}
958 962
 
... ...
@@ -968,36 +999,67 @@ int cdiff_apply(int fd, unsigned short mode)
968 968
 	if(sscanf(buff, "ClamAV-Diff:%*u:%u:", &difflen) != 1) {
969 969
 	    logg("!cdiff_apply: Incorrect file format\n");
970 970
 	    close(desc);
971
+	    free(line);
972
+	    free(lbuf);
971 973
 	    return -1;
972 974
 	}
973 975
 
974 976
 	if(!(gzh = gzdopen(desc, "rb"))) {
975 977
 	    logg("!cdiff_apply: Can't gzdopen descriptor %d\n", desc);
976 978
 	    close(desc);
979
+	    free(line);
980
+	    free(lbuf);
977 981
 	    return -1;
978 982
 	}
979 983
 
980 984
 	diffremain = difflen;
981 985
 	while(diffremain) {
982
-	    unsigned int bufsize = diffremain < sizeof(line) ? diffremain + 1 : sizeof(line);
986
+	    unsigned int bufsize = diffremain < line_size ? diffremain + 1 : line_size;
983 987
 
984 988
 	    if(!gzgets(gzh, line, bufsize)) {
985 989
 		logg("!cdiff_apply: Premature EOF at line %d\n", lines + 1);
986 990
 		cdiff_ctx_free(&ctx);
987 991
 		gzclose(gzh);
992
+		free(line);
993
+		free(lbuf);
988 994
 		return -1;
989 995
 	    }
990 996
 	    diffremain -= strlen(line);
991 997
 	    lines++;
992 998
 	    cli_chomp(line);
993 999
 
994
-	    if(line[0] == '#' || !strlen(line))
1000
+	    if(!strlen(line))
995 1001
 		continue;
1002
+	    if(line[0] == '#') {
1003
+		if(!strncmp(line, "#LSIZE", 6) && sscanf(line, "#LSIZE %u", &line_size) == 1) {
1004
+			char *r1, *r2;
1005
+		    if(line_size < CDIFF_LINE_SIZE || line_size > 10485760) {
1006
+			logg("^cdiff_apply: Ignoring new buffer size request - invalid size %d\n", line_size);
1007
+			line_size = CDIFF_LINE_SIZE;
1008
+			continue;
1009
+		    }
1010
+		    r1 = realloc(line, line_size);
1011
+		    r2 = realloc(lbuf, line_size);
1012
+		    if(!r1 || !r2) {
1013
+			logg("!cdiff_apply: Can't resize line buffer to %d bytes\n", line_size);
1014
+			cdiff_ctx_free(&ctx);
1015
+			fclose(fh);
1016
+			free(line);
1017
+			free(lbuf);
1018
+			return -1;
1019
+		    }
1020
+		    line = r1;
1021
+		    lbuf = r2;
1022
+		}
1023
+		continue;
1024
+	    }
996 1025
 
997
-	    if(cdiff_execute(line, &ctx) == -1) {
1026
+	    if(cdiff_execute(line, &ctx, lbuf, line_size) == -1) {
998 1027
 		logg("!cdiff_apply: Error executing command at line %d\n", lines);
999 1028
 		cdiff_ctx_free(&ctx);
1000 1029
 		gzclose(gzh);
1030
+		free(line);
1031
+		free(lbuf);
1001 1032
 		return -1;
1002 1033
 	    } else {
1003 1034
 		cmds++;
... ...
@@ -1010,20 +1072,47 @@ int cdiff_apply(int fd, unsigned short mode)
1010 1010
 	if(!(fh = fdopen(desc, "r"))) {
1011 1011
 	    logg("!cdiff_apply: fdopen() failed for descriptor %d\n", desc);
1012 1012
 	    close(desc);
1013
+	    free(line);
1014
+	    free(lbuf);
1013 1015
 	    return -1;
1014 1016
 	}
1015 1017
 
1016
-	while(fgets(line, sizeof(line), fh)) {
1018
+	while(fgets(line, line_size, fh)) {
1017 1019
 	    lines++;
1018 1020
 	    cli_chomp(line);
1019 1021
 
1020
-	    if(line[0] == '#' || !strlen(line))
1022
+	    if(!strlen(line))
1021 1023
 		continue;
1024
+	    if(line[0] == '#') {
1025
+		if(!strncmp(line, "#LSIZE", 6) && sscanf(line, "#LSIZE %u", &line_size) == 1) {
1026
+			char *r1, *r2;
1027
+		    if(line_size < CDIFF_LINE_SIZE || line_size > 10485760) {
1028
+			logg("^cdiff_apply: Ignoring new buffer size request - invalid size %d\n", line_size);
1029
+			line_size = CDIFF_LINE_SIZE;
1030
+			continue;
1031
+		    }
1032
+		    r1 = realloc(line, line_size);
1033
+		    r2 = realloc(lbuf, line_size);
1034
+		    if(!r1 || !r2) {
1035
+			logg("!cdiff_apply: Can't resize line buffer to %d bytes\n", line_size);
1036
+			cdiff_ctx_free(&ctx);
1037
+			fclose(fh);
1038
+			free(line);
1039
+			free(lbuf);
1040
+			return -1;
1041
+		    }
1042
+		    line = r1;
1043
+		    lbuf = r2;
1044
+		}
1045
+		continue;
1046
+	    }
1022 1047
 
1023
-	    if(cdiff_execute(line, &ctx) == -1) {
1048
+	    if(cdiff_execute(line, &ctx, lbuf, line_size) == -1) {
1024 1049
 		logg("!cdiff_apply: Error executing command at line %d\n", lines);
1025 1050
 		cdiff_ctx_free(&ctx);
1026 1051
 		fclose(fh);
1052
+		free(line);
1053
+		free(lbuf);
1027 1054
 		return -1;
1028 1055
 	    } else {
1029 1056
 		cmds++;
... ...
@@ -1033,6 +1122,9 @@ int cdiff_apply(int fd, unsigned short mode)
1033 1033
 	fclose(fh);
1034 1034
     }
1035 1035
 
1036
+    free(line);
1037
+    free(lbuf);
1038
+
1036 1039
     if(ctx.open_db) {
1037 1040
 	logg("*cdiff_apply: File %s was not properly closed\n", ctx.open_db);
1038 1041
 	cdiff_ctx_free(&ctx);