]>
Commit | Line | Data |
---|---|---|
9fd17760 ER |
1 | --- a/ext/standard/dns.c 2014-08-13 19:22:50.000000000 +0000 |
2 | +++ b/ext/standard/dns.c 2014-10-12 20:00:54.000000000 +0000 | |
3 | @@ -412,8 +412,14 @@ | |
4 | ||
5 | #if HAVE_FULL_DNS_FUNCS | |
6 | ||
7 | +#define CHECKCP(n) do { \ | |
8 | + if (cp + n > end) { \ | |
9 | + return NULL; \ | |
10 | + } \ | |
11 | +} while (0) | |
12 | + | |
13 | /* {{{ php_parserr */ | |
14 | -static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int store, zval **subarray) | |
15 | +static u_char *php_parserr(u_char *cp, u_char *end, querybuf *answer, int type_to_fetch, int store, zval **subarray) | |
16 | { | |
17 | u_short type, class, dlen; | |
18 | u_long ttl; | |
19 | @@ -425,16 +431,18 @@ | |
20 | ||
21 | *subarray = NULL; | |
22 | ||
23 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, sizeof(name) - 2); | |
24 | + n = dn_expand(answer->qb2, end, cp, name, sizeof(name) - 2); | |
25 | if (n < 0) { | |
26 | return NULL; | |
27 | } | |
28 | cp += n; | |
29 | ||
30 | + CHECKCP(10); | |
31 | GETSHORT(type, cp); | |
32 | GETSHORT(class, cp); | |
33 | GETLONG(ttl, cp); | |
34 | GETSHORT(dlen, cp); | |
35 | + CHECKCP(dlen); | |
36 | if (type_to_fetch != T_ANY && type != type_to_fetch) { | |
37 | cp += dlen; | |
38 | return cp; | |
39 | @@ -451,12 +459,14 @@ | |
40 | add_assoc_string(*subarray, "host", name, 1); | |
41 | switch (type) { | |
42 | case DNS_T_A: | |
43 | + CHECKCP(4); | |
44 | add_assoc_string(*subarray, "type", "A", 1); | |
45 | snprintf(name, sizeof(name), "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]); | |
46 | add_assoc_string(*subarray, "ip", name, 1); | |
47 | cp += dlen; | |
48 | break; | |
49 | case DNS_T_MX: | |
50 | + CHECKCP(2); | |
51 | add_assoc_string(*subarray, "type", "MX", 1); | |
52 | GETSHORT(n, cp); | |
53 | add_assoc_long(*subarray, "pri", n); | |
54 | @@ -475,7 +485,7 @@ | |
55 | if (type == DNS_T_PTR) { | |
56 | add_assoc_string(*subarray, "type", "PTR", 1); | |
57 | } | |
58 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); | |
59 | + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); | |
60 | if (n < 0) { | |
61 | return NULL; | |
62 | } | |
63 | @@ -485,18 +495,22 @@ | |
64 | case DNS_T_HINFO: | |
65 | /* See RFC 1010 for values */ | |
66 | add_assoc_string(*subarray, "type", "HINFO", 1); | |
67 | + CHECKCP(1); | |
68 | n = *cp & 0xFF; | |
69 | cp++; | |
70 | + CHECKCP(n); | |
71 | add_assoc_stringl(*subarray, "cpu", (char*)cp, n, 1); | |
72 | cp += n; | |
73 | + CHECKCP(1); | |
74 | n = *cp & 0xFF; | |
75 | cp++; | |
76 | + CHECKCP(n); | |
77 | add_assoc_stringl(*subarray, "os", (char*)cp, n, 1); | |
78 | cp += n; | |
79 | break; | |
80 | case DNS_T_TXT: | |
81 | { | |
82 | - int ll = 0; | |
83 | + int l1 = 0, l2 = 0; | |
84 | zval *entries = NULL; | |
85 | ||
86 | add_assoc_string(*subarray, "type", "TXT", 1); | |
87 | @@ -505,37 +519,42 @@ | |
88 | MAKE_STD_ZVAL(entries); | |
89 | array_init(entries); | |
90 | ||
91 | - while (ll < dlen) { | |
92 | - n = cp[ll]; | |
93 | - if ((ll + n) >= dlen) { | |
94 | + while (l1 < dlen) { | |
95 | + n = cp[l1]; | |
96 | + if ((l1 + n) >= dlen) { | |
97 | // Invalid chunk length, truncate | |
98 | - n = dlen - (ll + 1); | |
99 | + n = dlen - (l1 + 1); | |
100 | + } | |
101 | + if (n) { | |
102 | + memcpy(tp + l2 , cp + l1 + 1, n); | |
103 | + add_next_index_stringl(entries, cp + l1 + 1, n, 1); | |
104 | } | |
105 | - memcpy(tp + ll , cp + ll + 1, n); | |
106 | - add_next_index_stringl(entries, cp + ll + 1, n, 1); | |
107 | - ll = ll + n + 1; | |
108 | + l1 = l1 + n + 1; | |
109 | + l2 = l2 + n; | |
110 | } | |
111 | tp[dlen] = '\0'; | |
112 | + tp[l2] = '\0'; | |
113 | cp += dlen; | |
114 | ||
115 | - add_assoc_stringl(*subarray, "txt", tp, (dlen>0)?dlen - 1:0, 0); | |
116 | + add_assoc_stringl(*subarray, "txt", tp, l2, 0); | |
117 | add_assoc_zval(*subarray, "entries", entries); | |
118 | } | |
119 | break; | |
120 | case DNS_T_SOA: | |
121 | add_assoc_string(*subarray, "type", "SOA", 1); | |
122 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2); | |
123 | + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2); | |
124 | if (n < 0) { | |
125 | return NULL; | |
126 | } | |
127 | cp += n; | |
128 | add_assoc_string(*subarray, "mname", name, 1); | |
129 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2); | |
130 | + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2); | |
131 | if (n < 0) { | |
132 | return NULL; | |
133 | } | |
134 | cp += n; | |
135 | add_assoc_string(*subarray, "rname", name, 1); | |
136 | + CHECKCP(5*4); | |
137 | GETLONG(n, cp); | |
138 | add_assoc_long(*subarray, "serial", n); | |
139 | GETLONG(n, cp); | |
140 | @@ -549,6 +568,7 @@ | |
141 | break; | |
142 | case DNS_T_AAAA: | |
143 | tp = (u_char*)name; | |
144 | + CHECKCP(8*2); | |
145 | for(i=0; i < 8; i++) { | |
146 | GETSHORT(s, cp); | |
147 | if (s != 0) { | |
148 | @@ -583,6 +603,7 @@ | |
149 | case DNS_T_A6: | |
150 | p = cp; | |
151 | add_assoc_string(*subarray, "type", "A6", 1); | |
152 | + CHECKCP(1); | |
153 | n = ((int)cp[0]) & 0xFF; | |
154 | cp++; | |
155 | add_assoc_long(*subarray, "masklen", n); | |
156 | @@ -618,6 +639,7 @@ | |
157 | cp++; | |
158 | } | |
159 | for (i = (n + 8) / 16; i < 8; i++) { | |
160 | + CHECKCP(2); | |
161 | GETSHORT(s, cp); | |
162 | if (s != 0) { | |
163 | if (tp > (u_char *)name) { | |
164 | @@ -647,7 +669,7 @@ | |
165 | tp[0] = '\0'; | |
166 | add_assoc_string(*subarray, "ipv6", name, 1); | |
167 | if (cp < p + dlen) { | |
168 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); | |
169 | + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); | |
170 | if (n < 0) { | |
171 | return NULL; | |
172 | } | |
173 | @@ -656,6 +678,7 @@ | |
174 | } | |
175 | break; | |
176 | case DNS_T_SRV: | |
177 | + CHECKCP(3*2); | |
178 | add_assoc_string(*subarray, "type", "SRV", 1); | |
179 | GETSHORT(n, cp); | |
180 | add_assoc_long(*subarray, "pri", n); | |
181 | @@ -663,7 +686,7 @@ | |
182 | add_assoc_long(*subarray, "weight", n); | |
183 | GETSHORT(n, cp); | |
184 | add_assoc_long(*subarray, "port", n); | |
185 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); | |
186 | + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); | |
187 | if (n < 0) { | |
188 | return NULL; | |
189 | } | |
190 | @@ -671,21 +694,35 @@ | |
191 | add_assoc_string(*subarray, "target", name, 1); | |
192 | break; | |
193 | case DNS_T_NAPTR: | |
194 | + CHECKCP(2*2); | |
195 | add_assoc_string(*subarray, "type", "NAPTR", 1); | |
196 | GETSHORT(n, cp); | |
197 | add_assoc_long(*subarray, "order", n); | |
198 | GETSHORT(n, cp); | |
199 | add_assoc_long(*subarray, "pref", n); | |
200 | + | |
201 | + CHECKCP(1); | |
202 | n = (cp[0] & 0xFF); | |
203 | - add_assoc_stringl(*subarray, "flags", (char*)++cp, n, 1); | |
204 | + cp++; | |
205 | + CHECKCP(n); | |
206 | + add_assoc_stringl(*subarray, "flags", (char*)cp, n, 1); | |
207 | cp += n; | |
208 | + | |
209 | + CHECKCP(1); | |
210 | n = (cp[0] & 0xFF); | |
211 | - add_assoc_stringl(*subarray, "services", (char*)++cp, n, 1); | |
212 | + cp++; | |
213 | + CHECKCP(n); | |
214 | + add_assoc_stringl(*subarray, "services", (char*)cp, n, 1); | |
215 | cp += n; | |
216 | + | |
217 | + CHECKCP(1); | |
218 | n = (cp[0] & 0xFF); | |
219 | - add_assoc_stringl(*subarray, "regex", (char*)++cp, n, 1); | |
220 | + cp++; | |
221 | + CHECKCP(n); | |
222 | + add_assoc_stringl(*subarray, "regex", (char*)cp, n, 1); | |
223 | cp += n; | |
224 | - n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); | |
225 | + | |
226 | + n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); | |
227 | if (n < 0) { | |
228 | return NULL; | |
229 | } | |
230 | @@ -852,7 +889,7 @@ | |
231 | while (an-- && cp && cp < end) { | |
232 | zval *retval; | |
233 | ||
234 | - cp = php_parserr(cp, &answer, type_to_fetch, store_results, &retval); | |
235 | + cp = php_parserr(cp, end, &answer, type_to_fetch, store_results, &retval); | |
236 | if (retval != NULL && store_results) { | |
237 | add_next_index_zval(return_value, retval); | |
238 | } | |
239 | @@ -865,7 +902,7 @@ | |
240 | while (ns-- > 0 && cp && cp < end) { | |
241 | zval *retval = NULL; | |
242 | ||
243 | - cp = php_parserr(cp, &answer, DNS_T_ANY, authns != NULL, &retval); | |
244 | + cp = php_parserr(cp, end, &answer, DNS_T_ANY, authns != NULL, &retval); | |
245 | if (retval != NULL) { | |
246 | add_next_index_zval(authns, retval); | |
247 | } | |
248 | @@ -877,7 +914,7 @@ | |
249 | while (ar-- > 0 && cp && cp < end) { | |
250 | zval *retval = NULL; | |
251 | ||
252 | - cp = php_parserr(cp, &answer, DNS_T_ANY, 1, &retval); | |
253 | + cp = php_parserr(cp, end, &answer, DNS_T_ANY, 1, &retval); | |
254 | if (retval != NULL) { | |
255 | add_next_index_zval(addtl, retval); | |
256 | } |