diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-16 07:22:14 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-16 07:22:14 +0000 |
commit | bd9874db7485e827a2b9af6d7066c02692cef46d (patch) | |
tree | fef8728a85fef7666676a3e94b165f0d9c476ced /libbb | |
parent | 018bee6afb0a7b9e09616a52f2f24f65fcf07322 (diff) | |
download | busybox-w32-bd9874db7485e827a2b9af6d7066c02692cef46d.tar.gz busybox-w32-bd9874db7485e827a2b9af6d7066c02692cef46d.tar.bz2 busybox-w32-bd9874db7485e827a2b9af6d7066c02692cef46d.zip |
od,hexdump: fix bug where xrealloc may move pointer,
leaving other pointers dangling (bug 4104).
+ many style fixes in libbb/dump.c.
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/dump.c | 130 |
1 files changed, 68 insertions, 62 deletions
diff --git a/libbb/dump.c b/libbb/dump.c index 8a90aac5a..29c2c85ee 100644 --- a/libbb/dump.c +++ b/libbb/dump.c | |||
@@ -14,17 +14,18 @@ | |||
14 | #include "libbb.h" | 14 | #include "libbb.h" |
15 | #include "dump.h" | 15 | #include "dump.h" |
16 | 16 | ||
17 | enum _vflag bb_dump_vflag = FIRST; | 17 | FS *bb_dump_fshead; /* head of format strings */ |
18 | FS *bb_dump_fshead; /* head of format strings */ | 18 | off_t bb_dump_skip; /* bytes to skip */ |
19 | int bb_dump_blocksize; /* data block size */ | ||
20 | int bb_dump_length = -1; /* max bytes to read */ | ||
21 | smallint /*enum _vflag*/ bb_dump_vflag = FIRST; | ||
22 | |||
19 | static FU *endfu; | 23 | static FU *endfu; |
20 | static char **_argv; | 24 | static char **_argv; |
21 | static off_t savaddress; /* saved address/offset in stream */ | 25 | static off_t savaddress; /* saved address/offset in stream */ |
22 | static off_t eaddress; /* end address */ | 26 | static off_t eaddress; /* end address */ |
23 | static off_t address; /* address/offset in stream */ | 27 | static off_t address; /* address/offset in stream */ |
24 | off_t bb_dump_skip; /* bytes to skip */ | 28 | static int exitval; /* final exit value */ |
25 | static int exitval; /* final exit value */ | ||
26 | int bb_dump_blocksize; /* data block size */ | ||
27 | int bb_dump_length = -1; /* max bytes to read */ | ||
28 | 29 | ||
29 | static const char index_str[] ALIGN1 = ".#-+ 0123456789"; | 30 | static const char index_str[] ALIGN1 = ".#-+ 0123456789"; |
30 | 31 | ||
@@ -78,7 +79,7 @@ int FAST_FUNC bb_dump_size(FS *fs) | |||
78 | return cur_size; | 79 | return cur_size; |
79 | } | 80 | } |
80 | 81 | ||
81 | static void rewrite(FS * fs) | 82 | static void rewrite(FS *fs) |
82 | { | 83 | { |
83 | enum { NOTOKAY, USEBCNT, USEPREC } sokay; | 84 | enum { NOTOKAY, USEBCNT, USEPREC } sokay; |
84 | PR *pr, **nextpr = NULL; | 85 | PR *pr, **nextpr = NULL; |
@@ -104,7 +105,8 @@ static void rewrite(FS * fs) | |||
104 | */ | 105 | */ |
105 | 106 | ||
106 | /* bb_dump_skip preceding text and up to the next % sign */ | 107 | /* bb_dump_skip preceding text and up to the next % sign */ |
107 | for (p1 = fmtp; *p1 && *p1 != '%'; ++p1); | 108 | for (p1 = fmtp; *p1 && *p1 != '%'; ++p1) |
109 | continue; | ||
108 | 110 | ||
109 | /* only text in the string */ | 111 | /* only text in the string */ |
110 | if (!*p1) { | 112 | if (!*p1) { |
@@ -120,14 +122,17 @@ static void rewrite(FS * fs) | |||
120 | if (fu->bcnt) { | 122 | if (fu->bcnt) { |
121 | sokay = USEBCNT; | 123 | sokay = USEBCNT; |
122 | /* bb_dump_skip to conversion character */ | 124 | /* bb_dump_skip to conversion character */ |
123 | for (++p1; strchr(index_str, *p1); ++p1); | 125 | for (++p1; strchr(index_str, *p1); ++p1) |
126 | continue; | ||
124 | } else { | 127 | } else { |
125 | /* bb_dump_skip any special chars, field width */ | 128 | /* bb_dump_skip any special chars, field width */ |
126 | while (strchr(index_str + 1, *++p1)); | 129 | while (strchr(index_str + 1, *++p1)) |
130 | continue; | ||
127 | if (*p1 == '.' && isdigit(*++p1)) { | 131 | if (*p1 == '.' && isdigit(*++p1)) { |
128 | sokay = USEPREC; | 132 | sokay = USEPREC; |
129 | prec = atoi(p1); | 133 | prec = atoi(p1); |
130 | while (isdigit(*++p1)); | 134 | while (isdigit(*++p1)) |
135 | continue; | ||
131 | } else | 136 | } else |
132 | sokay = NOTOKAY; | 137 | sokay = NOTOKAY; |
133 | } | 138 | } |
@@ -139,12 +144,11 @@ static void rewrite(FS * fs) | |||
139 | * rewrite the format as necessary, set up blank- | 144 | * rewrite the format as necessary, set up blank- |
140 | * pbb_dump_adding for end of data. | 145 | * pbb_dump_adding for end of data. |
141 | */ | 146 | */ |
142 | |||
143 | if (*p1 == 'c') { | 147 | if (*p1 == 'c') { |
144 | pr->flags = F_CHAR; | 148 | pr->flags = F_CHAR; |
145 | DO_BYTE_COUNT_1: | 149 | DO_BYTE_COUNT_1: |
146 | byte_count_str = "\001"; | 150 | byte_count_str = "\001"; |
147 | DO_BYTE_COUNT: | 151 | DO_BYTE_COUNT: |
148 | if (fu->bcnt) { | 152 | if (fu->bcnt) { |
149 | do { | 153 | do { |
150 | if (fu->bcnt == *byte_count_str) { | 154 | if (fu->bcnt == *byte_count_str) { |
@@ -160,7 +164,7 @@ static void rewrite(FS * fs) | |||
160 | } else if (*p1 == 'l') { | 164 | } else if (*p1 == 'l') { |
161 | ++p2; | 165 | ++p2; |
162 | ++p1; | 166 | ++p1; |
163 | DO_INT_CONV: | 167 | DO_INT_CONV: |
164 | { | 168 | { |
165 | const char *e; | 169 | const char *e; |
166 | e = strchr(lcc, *p1); | 170 | e = strchr(lcc, *p1); |
@@ -221,7 +225,7 @@ static void rewrite(FS * fs) | |||
221 | goto DO_BAD_CONV_CHAR; | 225 | goto DO_BAD_CONV_CHAR; |
222 | } | 226 | } |
223 | } else { | 227 | } else { |
224 | DO_BAD_CONV_CHAR: | 228 | DO_BAD_CONV_CHAR: |
225 | bb_error_msg_and_die("bad conversion character %%%s", p1); | 229 | bb_error_msg_and_die("bad conversion character %%%s", p1); |
226 | } | 230 | } |
227 | 231 | ||
@@ -233,16 +237,17 @@ static void rewrite(FS * fs) | |||
233 | p1[1] = '\0'; | 237 | p1[1] = '\0'; |
234 | pr->fmt = xstrdup(fmtp); | 238 | pr->fmt = xstrdup(fmtp); |
235 | *p2 = savech; | 239 | *p2 = savech; |
236 | pr->cchar = pr->fmt + (p1 - fmtp); | 240 | //Too early! xrealloc can move pr->fmt! |
241 | //pr->cchar = pr->fmt + (p1 - fmtp); | ||
237 | 242 | ||
238 | /* DBU:[dave@cray.com] w/o this, trailing fmt text, space is lost. | 243 | /* DBU:[dave@cray.com] w/o this, trailing fmt text, space is lost. |
239 | * Skip subsequent text and up to the next % sign and tack the | 244 | * Skip subsequent text and up to the next % sign and tack the |
240 | * additional text onto fmt: eg. if fmt is "%x is a HEX number", | 245 | * additional text onto fmt: eg. if fmt is "%x is a HEX number", |
241 | * we lose the " is a HEX number" part of fmt. | 246 | * we lose the " is a HEX number" part of fmt. |
242 | */ | 247 | */ |
243 | for (p3 = p2; *p3 && *p3 != '%'; p3++); | 248 | for (p3 = p2; *p3 && *p3 != '%'; p3++) |
244 | if (p3 > p2) | 249 | continue; |
245 | { | 250 | if (p3 > p2) { |
246 | savech = *p3; | 251 | savech = *p3; |
247 | *p3 = '\0'; | 252 | *p3 = '\0'; |
248 | pr->fmt = xrealloc(pr->fmt, strlen(pr->fmt) + (p3-p2) + 1); | 253 | pr->fmt = xrealloc(pr->fmt, strlen(pr->fmt) + (p3-p2) + 1); |
@@ -251,6 +256,7 @@ static void rewrite(FS * fs) | |||
251 | p2 = p3; | 256 | p2 = p3; |
252 | } | 257 | } |
253 | 258 | ||
259 | pr->cchar = pr->fmt + (p1 - fmtp); | ||
254 | fmtp = p2; | 260 | fmtp = p2; |
255 | 261 | ||
256 | /* only one conversion character if byte count */ | 262 | /* only one conversion character if byte count */ |
@@ -276,9 +282,11 @@ static void rewrite(FS * fs) | |||
276 | * gets output from the last iteration of the format unit. | 282 | * gets output from the last iteration of the format unit. |
277 | */ | 283 | */ |
278 | for (fu = fs->nextfu;; fu = fu->nextfu) { | 284 | for (fu = fs->nextfu;; fu = fu->nextfu) { |
279 | if (!fu->nextfu && fs->bcnt < bb_dump_blocksize && | 285 | if (!fu->nextfu && fs->bcnt < bb_dump_blocksize |
280 | !(fu->flags & F_SETREP) && fu->bcnt) | 286 | && !(fu->flags & F_SETREP) && fu->bcnt |
287 | ) { | ||
281 | fu->reps += (bb_dump_blocksize - fs->bcnt) / fu->bcnt; | 288 | fu->reps += (bb_dump_blocksize - fs->bcnt) / fu->bcnt; |
289 | } | ||
282 | if (fu->reps > 1) { | 290 | if (fu->reps > 1) { |
283 | for (pr = fu->nextpr;; pr = pr->nextpr) | 291 | for (pr = fu->nextpr;; pr = pr->nextpr) |
284 | if (!pr->nextpr) | 292 | if (!pr->nextpr) |
@@ -377,7 +385,7 @@ static unsigned char *get(void) | |||
377 | * and no other files are available, zero-pad the rest of the | 385 | * and no other files are available, zero-pad the rest of the |
378 | * block and set the end flag. | 386 | * block and set the end flag. |
379 | */ | 387 | */ |
380 | if (!bb_dump_length || (ateof && !next((char **) NULL))) { | 388 | if (!bb_dump_length || (ateof && !next(NULL))) { |
381 | if (need == bb_dump_blocksize) { | 389 | if (need == bb_dump_blocksize) { |
382 | return NULL; | 390 | return NULL; |
383 | } | 391 | } |
@@ -387,12 +395,12 @@ static unsigned char *get(void) | |||
387 | } | 395 | } |
388 | return NULL; | 396 | return NULL; |
389 | } | 397 | } |
390 | memset((char *) curp + nread, 0, need); | 398 | memset(curp + nread, 0, need); |
391 | eaddress = address + nread; | 399 | eaddress = address + nread; |
392 | return curp; | 400 | return curp; |
393 | } | 401 | } |
394 | n = fread((char *) curp + nread, sizeof(unsigned char), | 402 | n = fread(curp + nread, sizeof(unsigned char), |
395 | bb_dump_length == -1 ? need : MIN(bb_dump_length, need), stdin); | 403 | bb_dump_length == -1 ? need : MIN(bb_dump_length, need), stdin); |
396 | if (!n) { | 404 | if (!n) { |
397 | if (ferror(stdin)) { | 405 | if (ferror(stdin)) { |
398 | bb_simple_perror_msg(_argv[-1]); | 406 | bb_simple_perror_msg(_argv[-1]); |
@@ -407,7 +415,8 @@ static unsigned char *get(void) | |||
407 | need -= n; | 415 | need -= n; |
408 | if (!need) { | 416 | if (!need) { |
409 | if (bb_dump_vflag == ALL || bb_dump_vflag == FIRST | 417 | if (bb_dump_vflag == ALL || bb_dump_vflag == FIRST |
410 | || memcmp(curp, savp, bb_dump_blocksize)) { | 418 | || memcmp(curp, savp, bb_dump_blocksize) |
419 | ) { | ||
411 | if (bb_dump_vflag == DUP || bb_dump_vflag == FIRST) { | 420 | if (bb_dump_vflag == DUP || bb_dump_vflag == FIRST) { |
412 | bb_dump_vflag = WAIT; | 421 | bb_dump_vflag = WAIT; |
413 | } | 422 | } |
@@ -426,7 +435,7 @@ static unsigned char *get(void) | |||
426 | } | 435 | } |
427 | } | 436 | } |
428 | 437 | ||
429 | static void bpad(PR * pr) | 438 | static void bpad(PR *pr) |
430 | { | 439 | { |
431 | char *p1, *p2; | 440 | char *p1, *p2; |
432 | 441 | ||
@@ -436,10 +445,13 @@ static void bpad(PR * pr) | |||
436 | */ | 445 | */ |
437 | pr->flags = F_BPAD; | 446 | pr->flags = F_BPAD; |
438 | *pr->cchar = 's'; | 447 | *pr->cchar = 's'; |
439 | for (p1 = pr->fmt; *p1 != '%'; ++p1); | 448 | for (p1 = pr->fmt; *p1 != '%'; ++p1) |
449 | continue; | ||
440 | for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1) | 450 | for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1) |
441 | if (pr->nospace) pr->nospace--; | 451 | if (pr->nospace) |
442 | while ((*p2++ = *p1++) != 0); | 452 | pr->nospace--; |
453 | while ((*p2++ = *p1++) != 0) | ||
454 | continue; | ||
443 | } | 455 | } |
444 | 456 | ||
445 | static const char conv_str[] ALIGN1 = | 457 | static const char conv_str[] ALIGN1 = |
@@ -454,7 +466,7 @@ static const char conv_str[] ALIGN1 = | |||
454 | ; | 466 | ; |
455 | 467 | ||
456 | 468 | ||
457 | static void conv_c(PR * pr, unsigned char * p) | 469 | static void conv_c(PR *pr, unsigned char *p) |
458 | { | 470 | { |
459 | const char *str = conv_str; | 471 | const char *str = conv_str; |
460 | char buf[10]; | 472 | char buf[10]; |
@@ -469,7 +481,7 @@ static void conv_c(PR * pr, unsigned char * p) | |||
469 | 481 | ||
470 | if (isprint(*p)) { | 482 | if (isprint(*p)) { |
471 | *pr->cchar = 'c'; | 483 | *pr->cchar = 'c'; |
472 | (void) printf(pr->fmt, *p); | 484 | printf(pr->fmt, *p); |
473 | } else { | 485 | } else { |
474 | sprintf(buf, "%03o", (int) *p); | 486 | sprintf(buf, "%03o", (int) *p); |
475 | str = buf; | 487 | str = buf; |
@@ -479,7 +491,7 @@ static void conv_c(PR * pr, unsigned char * p) | |||
479 | } | 491 | } |
480 | } | 492 | } |
481 | 493 | ||
482 | static void conv_u(PR * pr, unsigned char * p) | 494 | static void conv_u(PR *pr, unsigned char *p) |
483 | { | 495 | { |
484 | static const char list[] ALIGN1 = | 496 | static const char list[] ALIGN1 = |
485 | "nul\0soh\0stx\0etx\0eot\0enq\0ack\0bel\0" | 497 | "nul\0soh\0stx\0etx\0eot\0enq\0ack\0bel\0" |
@@ -511,7 +523,6 @@ static void display(void) | |||
511 | PR *pr; | 523 | PR *pr; |
512 | int cnt; | 524 | int cnt; |
513 | unsigned char *bp; | 525 | unsigned char *bp; |
514 | |||
515 | off_t saveaddress; | 526 | off_t saveaddress; |
516 | unsigned char savech = 0, *savebp; | 527 | unsigned char savech = 0, *savebp; |
517 | 528 | ||
@@ -536,7 +547,7 @@ static void display(void) | |||
536 | /* PRINT; */ | 547 | /* PRINT; */ |
537 | switch (pr->flags) { | 548 | switch (pr->flags) { |
538 | case F_ADDRESS: | 549 | case F_ADDRESS: |
539 | printf(pr->fmt, (unsigned int) address); | 550 | printf(pr->fmt, (unsigned) address); |
540 | break; | 551 | break; |
541 | case F_BPAD: | 552 | case F_BPAD: |
542 | printf(pr->fmt, ""); | 553 | printf(pr->fmt, ""); |
@@ -553,13 +564,11 @@ static void display(void) | |||
553 | 564 | ||
554 | switch (pr->bcnt) { | 565 | switch (pr->bcnt) { |
555 | case 4: | 566 | case 4: |
556 | memmove((char *) &fval, (char *) bp, | 567 | memmove(&fval, bp, sizeof(fval)); |
557 | sizeof(fval)); | ||
558 | printf(pr->fmt, fval); | 568 | printf(pr->fmt, fval); |
559 | break; | 569 | break; |
560 | case 8: | 570 | case 8: |
561 | memmove((char *) &dval, (char *) bp, | 571 | memmove(&dval, bp, sizeof(dval)); |
562 | sizeof(dval)); | ||
563 | printf(pr->fmt, dval); | 572 | printf(pr->fmt, dval); |
564 | break; | 573 | break; |
565 | } | 574 | } |
@@ -574,13 +583,11 @@ static void display(void) | |||
574 | printf(pr->fmt, (int) *bp); | 583 | printf(pr->fmt, (int) *bp); |
575 | break; | 584 | break; |
576 | case 2: | 585 | case 2: |
577 | memmove((char *) &sval, (char *) bp, | 586 | memmove(&sval, bp, sizeof(sval)); |
578 | sizeof(sval)); | ||
579 | printf(pr->fmt, (int) sval); | 587 | printf(pr->fmt, (int) sval); |
580 | break; | 588 | break; |
581 | case 4: | 589 | case 4: |
582 | memmove((char *) &ival, (char *) bp, | 590 | memmove(&ival, bp, sizeof(ival)); |
583 | sizeof(ival)); | ||
584 | printf(pr->fmt, ival); | 591 | printf(pr->fmt, ival); |
585 | break; | 592 | break; |
586 | } | 593 | } |
@@ -599,21 +606,19 @@ static void display(void) | |||
599 | conv_u(pr, bp); | 606 | conv_u(pr, bp); |
600 | break; | 607 | break; |
601 | case F_UINT:{ | 608 | case F_UINT:{ |
602 | unsigned int ival; | 609 | unsigned ival; |
603 | unsigned short sval; | 610 | unsigned short sval; |
604 | 611 | ||
605 | switch (pr->bcnt) { | 612 | switch (pr->bcnt) { |
606 | case 1: | 613 | case 1: |
607 | printf(pr->fmt, (unsigned int) * bp); | 614 | printf(pr->fmt, (unsigned) *bp); |
608 | break; | 615 | break; |
609 | case 2: | 616 | case 2: |
610 | memmove((char *) &sval, (char *) bp, | 617 | memmove(&sval, bp, sizeof(sval)); |
611 | sizeof(sval)); | 618 | printf(pr->fmt, (unsigned) sval); |
612 | printf(pr->fmt, (unsigned int) sval); | ||
613 | break; | 619 | break; |
614 | case 4: | 620 | case 4: |
615 | memmove((char *) &ival, (char *) bp, | 621 | memmove(&ival, bp, sizeof(ival)); |
616 | sizeof(ival)); | ||
617 | printf(pr->fmt, ival); | 622 | printf(pr->fmt, ival); |
618 | break; | 623 | break; |
619 | } | 624 | } |
@@ -642,10 +647,10 @@ static void display(void) | |||
642 | for (pr = endfu->nextpr; pr; pr = pr->nextpr) { | 647 | for (pr = endfu->nextpr; pr; pr = pr->nextpr) { |
643 | switch (pr->flags) { | 648 | switch (pr->flags) { |
644 | case F_ADDRESS: | 649 | case F_ADDRESS: |
645 | (void) printf(pr->fmt, (unsigned int) eaddress); | 650 | printf(pr->fmt, (unsigned) eaddress); |
646 | break; | 651 | break; |
647 | case F_TEXT: | 652 | case F_TEXT: |
648 | (void) printf(pr->fmt); | 653 | printf(pr->fmt); |
649 | break; | 654 | break; |
650 | } | 655 | } |
651 | } | 656 | } |
@@ -676,10 +681,11 @@ int FAST_FUNC bb_dump_dump(char **argv) | |||
676 | 681 | ||
677 | void FAST_FUNC bb_dump_add(const char *fmt) | 682 | void FAST_FUNC bb_dump_add(const char *fmt) |
678 | { | 683 | { |
684 | static FS **nextfs; | ||
685 | |||
679 | const char *p; | 686 | const char *p; |
680 | char *p1; | 687 | char *p1; |
681 | char *p2; | 688 | char *p2; |
682 | static FS **nextfs; | ||
683 | FS *tfs; | 689 | FS *tfs; |
684 | FU *tfu, **nextfu; | 690 | FU *tfu, **nextfu; |
685 | const char *savep; | 691 | const char *savep; |
@@ -712,7 +718,8 @@ void FAST_FUNC bb_dump_add(const char *fmt) | |||
712 | 718 | ||
713 | /* if leading digit, repetition count */ | 719 | /* if leading digit, repetition count */ |
714 | if (isdigit(*p)) { | 720 | if (isdigit(*p)) { |
715 | for (savep = p; isdigit(*p); ++p); | 721 | for (savep = p; isdigit(*p); ++p) |
722 | continue; | ||
716 | if (!isspace(*p) && *p != '/') { | 723 | if (!isspace(*p) && *p != '/') { |
717 | bb_error_msg_and_die("bad format {%s}", fmt); | 724 | bb_error_msg_and_die("bad format {%s}", fmt); |
718 | } | 725 | } |
@@ -732,7 +739,8 @@ void FAST_FUNC bb_dump_add(const char *fmt) | |||
732 | if (isdigit(*p)) { | 739 | if (isdigit(*p)) { |
733 | // TODO: use bb_strtou | 740 | // TODO: use bb_strtou |
734 | savep = p; | 741 | savep = p; |
735 | do p++; while (isdigit(*p)); | 742 | while (isdigit(*++p)) |
743 | continue; | ||
736 | if (!isspace(*p)) { | 744 | if (!isspace(*p)) { |
737 | bb_error_msg_and_die("bad format {%s}", fmt); | 745 | bb_error_msg_and_die("bad format {%s}", fmt); |
738 | } | 746 | } |
@@ -750,9 +758,7 @@ void FAST_FUNC bb_dump_add(const char *fmt) | |||
750 | bb_error_msg_and_die("bad format {%s}", fmt); | 758 | bb_error_msg_and_die("bad format {%s}", fmt); |
751 | } | 759 | } |
752 | } | 760 | } |
753 | tfu->fmt = xmalloc(p - savep + 1); | 761 | tfu->fmt = xstrndup(savep, p - savep); |
754 | strncpy(tfu->fmt, savep, p - savep); | ||
755 | tfu->fmt[p - savep] = '\0'; | ||
756 | /* escape(tfu->fmt); */ | 762 | /* escape(tfu->fmt); */ |
757 | 763 | ||
758 | p1 = tfu->fmt; | 764 | p1 = tfu->fmt; |