diff options
Diffstat (limited to 'inflate.c')
-rw-r--r-- | inflate.c | 123 |
1 files changed, 78 insertions, 45 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* inflate.c -- zlib decompression | 1 | /* inflate.c -- zlib decompression |
2 | * Copyright (C) 1995-2005 Mark Adler | 2 | * Copyright (C) 1995-2006 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -121,6 +121,7 @@ z_streamp strm; | |||
121 | state->hold = 0; | 121 | state->hold = 0; |
122 | state->bits = 0; | 122 | state->bits = 0; |
123 | state->lencode = state->distcode = state->next = state->codes; | 123 | state->lencode = state->distcode = state->next = state->codes; |
124 | state->sane = 1; | ||
124 | Tracev((stderr, "inflate: reset\n")); | 125 | Tracev((stderr, "inflate: reset\n")); |
125 | return Z_OK; | 126 | return Z_OK; |
126 | } | 127 | } |
@@ -564,7 +565,7 @@ int flush; | |||
564 | unsigned in, out; /* save starting available input and output */ | 565 | unsigned in, out; /* save starting available input and output */ |
565 | unsigned copy; /* number of stored or match bytes to copy */ | 566 | unsigned copy; /* number of stored or match bytes to copy */ |
566 | unsigned char FAR *from; /* where to copy match bytes from */ | 567 | unsigned char FAR *from; /* where to copy match bytes from */ |
567 | code this; /* current decoding table entry */ | 568 | code here; /* current decoding table entry */ |
568 | code last; /* parent table entry */ | 569 | code last; /* parent table entry */ |
569 | unsigned len; /* length to copy for repeats, bits to drop */ | 570 | unsigned len; /* length to copy for repeats, bits to drop */ |
570 | int ret; /* return code */ | 571 | int ret; /* return code */ |
@@ -876,19 +877,19 @@ int flush; | |||
876 | case CODELENS: | 877 | case CODELENS: |
877 | while (state->have < state->nlen + state->ndist) { | 878 | while (state->have < state->nlen + state->ndist) { |
878 | for (;;) { | 879 | for (;;) { |
879 | this = state->lencode[BITS(state->lenbits)]; | 880 | here = state->lencode[BITS(state->lenbits)]; |
880 | if ((unsigned)(this.bits) <= bits) break; | 881 | if ((unsigned)(here.bits) <= bits) break; |
881 | PULLBYTE(); | 882 | PULLBYTE(); |
882 | } | 883 | } |
883 | if (this.val < 16) { | 884 | if (here.val < 16) { |
884 | NEEDBITS(this.bits); | 885 | NEEDBITS(here.bits); |
885 | DROPBITS(this.bits); | 886 | DROPBITS(here.bits); |
886 | state->lens[state->have++] = this.val; | 887 | state->lens[state->have++] = here.val; |
887 | } | 888 | } |
888 | else { | 889 | else { |
889 | if (this.val == 16) { | 890 | if (here.val == 16) { |
890 | NEEDBITS(this.bits + 2); | 891 | NEEDBITS(here.bits + 2); |
891 | DROPBITS(this.bits); | 892 | DROPBITS(here.bits); |
892 | if (state->have == 0) { | 893 | if (state->have == 0) { |
893 | strm->msg = (char *)"invalid bit length repeat"; | 894 | strm->msg = (char *)"invalid bit length repeat"; |
894 | state->mode = BAD; | 895 | state->mode = BAD; |
@@ -898,16 +899,16 @@ int flush; | |||
898 | copy = 3 + BITS(2); | 899 | copy = 3 + BITS(2); |
899 | DROPBITS(2); | 900 | DROPBITS(2); |
900 | } | 901 | } |
901 | else if (this.val == 17) { | 902 | else if (here.val == 17) { |
902 | NEEDBITS(this.bits + 3); | 903 | NEEDBITS(here.bits + 3); |
903 | DROPBITS(this.bits); | 904 | DROPBITS(here.bits); |
904 | len = 0; | 905 | len = 0; |
905 | copy = 3 + BITS(3); | 906 | copy = 3 + BITS(3); |
906 | DROPBITS(3); | 907 | DROPBITS(3); |
907 | } | 908 | } |
908 | else { | 909 | else { |
909 | NEEDBITS(this.bits + 7); | 910 | NEEDBITS(here.bits + 7); |
910 | DROPBITS(this.bits); | 911 | DROPBITS(here.bits); |
911 | len = 0; | 912 | len = 0; |
912 | copy = 11 + BITS(7); | 913 | copy = 11 + BITS(7); |
913 | DROPBITS(7); | 914 | DROPBITS(7); |
@@ -955,40 +956,40 @@ int flush; | |||
955 | break; | 956 | break; |
956 | } | 957 | } |
957 | for (;;) { | 958 | for (;;) { |
958 | this = state->lencode[BITS(state->lenbits)]; | 959 | here = state->lencode[BITS(state->lenbits)]; |
959 | if ((unsigned)(this.bits) <= bits) break; | 960 | if ((unsigned)(here.bits) <= bits) break; |
960 | PULLBYTE(); | 961 | PULLBYTE(); |
961 | } | 962 | } |
962 | if (this.op && (this.op & 0xf0) == 0) { | 963 | if (here.op && (here.op & 0xf0) == 0) { |
963 | last = this; | 964 | last = here; |
964 | for (;;) { | 965 | for (;;) { |
965 | this = state->lencode[last.val + | 966 | here = state->lencode[last.val + |
966 | (BITS(last.bits + last.op) >> last.bits)]; | 967 | (BITS(last.bits + last.op) >> last.bits)]; |
967 | if ((unsigned)(last.bits + this.bits) <= bits) break; | 968 | if ((unsigned)(last.bits + here.bits) <= bits) break; |
968 | PULLBYTE(); | 969 | PULLBYTE(); |
969 | } | 970 | } |
970 | DROPBITS(last.bits); | 971 | DROPBITS(last.bits); |
971 | } | 972 | } |
972 | DROPBITS(this.bits); | 973 | DROPBITS(here.bits); |
973 | state->length = (unsigned)this.val; | 974 | state->length = (unsigned)here.val; |
974 | if ((int)(this.op) == 0) { | 975 | if ((int)(here.op) == 0) { |
975 | Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? | 976 | Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? |
976 | "inflate: literal '%c'\n" : | 977 | "inflate: literal '%c'\n" : |
977 | "inflate: literal 0x%02x\n", this.val)); | 978 | "inflate: literal 0x%02x\n", here.val)); |
978 | state->mode = LIT; | 979 | state->mode = LIT; |
979 | break; | 980 | break; |
980 | } | 981 | } |
981 | if (this.op & 32) { | 982 | if (here.op & 32) { |
982 | Tracevv((stderr, "inflate: end of block\n")); | 983 | Tracevv((stderr, "inflate: end of block\n")); |
983 | state->mode = TYPE; | 984 | state->mode = TYPE; |
984 | break; | 985 | break; |
985 | } | 986 | } |
986 | if (this.op & 64) { | 987 | if (here.op & 64) { |
987 | strm->msg = (char *)"invalid literal/length code"; | 988 | strm->msg = (char *)"invalid literal/length code"; |
988 | state->mode = BAD; | 989 | state->mode = BAD; |
989 | break; | 990 | break; |
990 | } | 991 | } |
991 | state->extra = (unsigned)(this.op) & 15; | 992 | state->extra = (unsigned)(here.op) & 15; |
992 | state->mode = LENEXT; | 993 | state->mode = LENEXT; |
993 | case LENEXT: | 994 | case LENEXT: |
994 | if (state->extra) { | 995 | if (state->extra) { |
@@ -1000,28 +1001,28 @@ int flush; | |||
1000 | state->mode = DIST; | 1001 | state->mode = DIST; |
1001 | case DIST: | 1002 | case DIST: |
1002 | for (;;) { | 1003 | for (;;) { |
1003 | this = state->distcode[BITS(state->distbits)]; | 1004 | here = state->distcode[BITS(state->distbits)]; |
1004 | if ((unsigned)(this.bits) <= bits) break; | 1005 | if ((unsigned)(here.bits) <= bits) break; |
1005 | PULLBYTE(); | 1006 | PULLBYTE(); |
1006 | } | 1007 | } |
1007 | if ((this.op & 0xf0) == 0) { | 1008 | if ((here.op & 0xf0) == 0) { |
1008 | last = this; | 1009 | last = here; |
1009 | for (;;) { | 1010 | for (;;) { |
1010 | this = state->distcode[last.val + | 1011 | here = state->distcode[last.val + |
1011 | (BITS(last.bits + last.op) >> last.bits)]; | 1012 | (BITS(last.bits + last.op) >> last.bits)]; |
1012 | if ((unsigned)(last.bits + this.bits) <= bits) break; | 1013 | if ((unsigned)(last.bits + here.bits) <= bits) break; |
1013 | PULLBYTE(); | 1014 | PULLBYTE(); |
1014 | } | 1015 | } |
1015 | DROPBITS(last.bits); | 1016 | DROPBITS(last.bits); |
1016 | } | 1017 | } |
1017 | DROPBITS(this.bits); | 1018 | DROPBITS(here.bits); |
1018 | if (this.op & 64) { | 1019 | if (here.op & 64) { |
1019 | strm->msg = (char *)"invalid distance code"; | 1020 | strm->msg = (char *)"invalid distance code"; |
1020 | state->mode = BAD; | 1021 | state->mode = BAD; |
1021 | break; | 1022 | break; |
1022 | } | 1023 | } |
1023 | state->offset = (unsigned)this.val; | 1024 | state->offset = (unsigned)here.val; |
1024 | state->extra = (unsigned)(this.op) & 15; | 1025 | state->extra = (unsigned)(here.op) & 15; |
1025 | state->mode = DISTEXT; | 1026 | state->mode = DISTEXT; |
1026 | case DISTEXT: | 1027 | case DISTEXT: |
1027 | if (state->extra) { | 1028 | if (state->extra) { |
@@ -1036,11 +1037,6 @@ int flush; | |||
1036 | break; | 1037 | break; |
1037 | } | 1038 | } |
1038 | #endif | 1039 | #endif |
1039 | if (state->offset > state->whave + out - left) { | ||
1040 | strm->msg = (char *)"invalid distance too far back"; | ||
1041 | state->mode = BAD; | ||
1042 | break; | ||
1043 | } | ||
1044 | Tracevv((stderr, "inflate: distance %u\n", state->offset)); | 1040 | Tracevv((stderr, "inflate: distance %u\n", state->offset)); |
1045 | state->mode = MATCH; | 1041 | state->mode = MATCH; |
1046 | case MATCH: | 1042 | case MATCH: |
@@ -1048,6 +1044,26 @@ int flush; | |||
1048 | copy = out - left; | 1044 | copy = out - left; |
1049 | if (state->offset > copy) { /* copy from window */ | 1045 | if (state->offset > copy) { /* copy from window */ |
1050 | copy = state->offset - copy; | 1046 | copy = state->offset - copy; |
1047 | if (copy > state->whave) { | ||
1048 | if (state->sane) { | ||
1049 | strm->msg = (char *)"invalid distance too far back"; | ||
1050 | state->mode = BAD; | ||
1051 | break; | ||
1052 | } | ||
1053 | #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR | ||
1054 | Trace((stderr, "inflate.c too far\n")); | ||
1055 | copy -= state->whave; | ||
1056 | if (copy > state->length) copy = state->length; | ||
1057 | if (copy > left) copy = left; | ||
1058 | left -= copy; | ||
1059 | state->length -= copy; | ||
1060 | do { | ||
1061 | *put++ = 0; | ||
1062 | } while (--copy); | ||
1063 | if (state->length == 0) state->mode = LEN; | ||
1064 | break; | ||
1065 | #endif | ||
1066 | } | ||
1051 | if (copy > state->write) { | 1067 | if (copy > state->write) { |
1052 | copy -= state->write; | 1068 | copy -= state->write; |
1053 | from = state->window + (state->wsize - copy); | 1069 | from = state->window + (state->wsize - copy); |
@@ -1366,3 +1382,20 @@ z_streamp source; | |||
1366 | dest->state = (struct internal_state FAR *)copy; | 1382 | dest->state = (struct internal_state FAR *)copy; |
1367 | return Z_OK; | 1383 | return Z_OK; |
1368 | } | 1384 | } |
1385 | |||
1386 | int ZEXPORT inflateUndermine(strm, subvert) | ||
1387 | z_streamp strm; | ||
1388 | int subvert; | ||
1389 | { | ||
1390 | struct inflate_state FAR *state; | ||
1391 | |||
1392 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | ||
1393 | state = (struct inflate_state FAR *)strm->state; | ||
1394 | #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR | ||
1395 | state->sane = !subvert; | ||
1396 | return Z_OK; | ||
1397 | #else | ||
1398 | state->sane = 1; | ||
1399 | return Z_DATA_ERROR; | ||
1400 | #endif | ||
1401 | } | ||