Coverage Report

Created: 2024-09-08 06:32

/src/nghttp2/lib/nghttp2_hd.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * nghttp2 - HTTP/2 C Library
3
 *
4
 * Copyright (c) 2013 Tatsuhiro Tsujikawa
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining
7
 * a copy of this software and associated documentation files (the
8
 * "Software"), to deal in the Software without restriction, including
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sublicense, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be
15
 * included in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
 */
25
#include "nghttp2_hd.h"
26
27
#include <string.h>
28
#include <assert.h>
29
#include <stdio.h>
30
31
#include "nghttp2_helper.h"
32
#include "nghttp2_int.h"
33
#include "nghttp2_debug.h"
34
35
/* Make scalar initialization form of nghttp2_hd_entry */
36
#define MAKE_STATIC_ENT(N, V, T, H)                                            \
37
  {                                                                            \
38
      {NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1},                       \
39
      {NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1},                       \
40
      {(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0},   \
41
      T,                                                                       \
42
      H,                                                                       \
43
  }
44
45
/* Generated by mkstatictbl.py */
46
/* 3rd parameter is nghttp2_token value for header field name.  We use
47
   first enum value if same header names are repeated (e.g.,
48
   :status). */
49
static const nghttp2_hd_static_entry static_table[] = {
50
    MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
51
    MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
52
    MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
53
    MAKE_STATIC_ENT(":path", "/", 3, 3292848686u),
54
    MAKE_STATIC_ENT(":path", "/index.html", 3, 3292848686u),
55
    MAKE_STATIC_ENT(":scheme", "http", 5, 2510477674u),
56
    MAKE_STATIC_ENT(":scheme", "https", 5, 2510477674u),
57
    MAKE_STATIC_ENT(":status", "200", 7, 4000288983u),
58
    MAKE_STATIC_ENT(":status", "204", 7, 4000288983u),
59
    MAKE_STATIC_ENT(":status", "206", 7, 4000288983u),
60
    MAKE_STATIC_ENT(":status", "304", 7, 4000288983u),
61
    MAKE_STATIC_ENT(":status", "400", 7, 4000288983u),
62
    MAKE_STATIC_ENT(":status", "404", 7, 4000288983u),
63
    MAKE_STATIC_ENT(":status", "500", 7, 4000288983u),
64
    MAKE_STATIC_ENT("accept-charset", "", 14, 3664010344u),
65
    MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15, 3379649177u),
66
    MAKE_STATIC_ENT("accept-language", "", 16, 1979086614u),
67
    MAKE_STATIC_ENT("accept-ranges", "", 17, 1713753958u),
68
    MAKE_STATIC_ENT("accept", "", 18, 136609321u),
69
    MAKE_STATIC_ENT("access-control-allow-origin", "", 19, 2710797292u),
70
    MAKE_STATIC_ENT("age", "", 20, 742476188u),
71
    MAKE_STATIC_ENT("allow", "", 21, 2930878514u),
72
    MAKE_STATIC_ENT("authorization", "", 22, 2436257726u),
73
    MAKE_STATIC_ENT("cache-control", "", 23, 1355326669u),
74
    MAKE_STATIC_ENT("content-disposition", "", 24, 3889184348u),
75
    MAKE_STATIC_ENT("content-encoding", "", 25, 65203592u),
76
    MAKE_STATIC_ENT("content-language", "", 26, 24973587u),
77
    MAKE_STATIC_ENT("content-length", "", 27, 1308181789u),
78
    MAKE_STATIC_ENT("content-location", "", 28, 2302364718u),
79
    MAKE_STATIC_ENT("content-range", "", 29, 3555523146u),
80
    MAKE_STATIC_ENT("content-type", "", 30, 4244048277u),
81
    MAKE_STATIC_ENT("cookie", "", 31, 2007449791u),
82
    MAKE_STATIC_ENT("date", "", 32, 3564297305u),
83
    MAKE_STATIC_ENT("etag", "", 33, 113792960u),
84
    MAKE_STATIC_ENT("expect", "", 34, 2530896728u),
85
    MAKE_STATIC_ENT("expires", "", 35, 1049544579u),
86
    MAKE_STATIC_ENT("from", "", 36, 2513272949u),
87
    MAKE_STATIC_ENT("host", "", 37, 2952701295u),
88
    MAKE_STATIC_ENT("if-match", "", 38, 3597694698u),
89
    MAKE_STATIC_ENT("if-modified-since", "", 39, 2213050793u),
90
    MAKE_STATIC_ENT("if-none-match", "", 40, 2536202615u),
91
    MAKE_STATIC_ENT("if-range", "", 41, 2340978238u),
92
    MAKE_STATIC_ENT("if-unmodified-since", "", 42, 3794814858u),
93
    MAKE_STATIC_ENT("last-modified", "", 43, 3226950251u),
94
    MAKE_STATIC_ENT("link", "", 44, 232457833u),
95
    MAKE_STATIC_ENT("location", "", 45, 200649126u),
96
    MAKE_STATIC_ENT("max-forwards", "", 46, 1826162134u),
97
    MAKE_STATIC_ENT("proxy-authenticate", "", 47, 2709445359u),
98
    MAKE_STATIC_ENT("proxy-authorization", "", 48, 2686392507u),
99
    MAKE_STATIC_ENT("range", "", 49, 4208725202u),
100
    MAKE_STATIC_ENT("referer", "", 50, 3969579366u),
101
    MAKE_STATIC_ENT("refresh", "", 51, 3572655668u),
102
    MAKE_STATIC_ENT("retry-after", "", 52, 3336180598u),
103
    MAKE_STATIC_ENT("server", "", 53, 1085029842u),
104
    MAKE_STATIC_ENT("set-cookie", "", 54, 1848371000u),
105
    MAKE_STATIC_ENT("strict-transport-security", "", 55, 4138147361u),
106
    MAKE_STATIC_ENT("transfer-encoding", "", 56, 3719590988u),
107
    MAKE_STATIC_ENT("user-agent", "", 57, 606444526u),
108
    MAKE_STATIC_ENT("vary", "", 58, 1085005381u),
109
    MAKE_STATIC_ENT("via", "", 59, 1762798611u),
110
    MAKE_STATIC_ENT("www-authenticate", "", 60, 779865858u),
111
};
112
113
930k
static int memeq(const void *s1, const void *s2, size_t n) {
114
930k
  return memcmp(s1, s2, n) == 0;
115
930k
}
116
117
/*
118
 * This function was generated by genlibtokenlookup.py.  Inspired by
119
 * h2o header lookup.  https://github.com/h2o/h2o
120
 */
121
465k
static int32_t lookup_token(const uint8_t *name, size_t namelen) {
122
465k
  switch (namelen) {
123
39.4k
  case 2:
124
39.4k
    switch (name[1]) {
125
8.34k
    case 'e':
126
8.34k
      if (memeq("t", name, 1)) {
127
2.47k
        return NGHTTP2_TOKEN_TE;
128
2.47k
      }
129
5.87k
      break;
130
39.4k
    }
131
36.9k
    break;
132
42.1k
  case 3:
133
42.1k
    switch (name[2]) {
134
6.75k
    case 'a':
135
6.75k
      if (memeq("vi", name, 2)) {
136
4.42k
        return NGHTTP2_TOKEN_VIA;
137
4.42k
      }
138
2.32k
      break;
139
5.61k
    case 'e':
140
5.61k
      if (memeq("ag", name, 2)) {
141
482
        return NGHTTP2_TOKEN_AGE;
142
482
      }
143
5.12k
      break;
144
42.1k
    }
145
37.2k
    break;
146
53.5k
  case 4:
147
53.5k
    switch (name[3]) {
148
9.74k
    case 'e':
149
9.74k
      if (memeq("dat", name, 3)) {
150
749
        return NGHTTP2_TOKEN_DATE;
151
749
      }
152
9.00k
      break;
153
9.00k
    case 'g':
154
8.22k
      if (memeq("eta", name, 3)) {
155
1.12k
        return NGHTTP2_TOKEN_ETAG;
156
1.12k
      }
157
7.09k
      break;
158
8.50k
    case 'k':
159
8.50k
      if (memeq("lin", name, 3)) {
160
3.66k
        return NGHTTP2_TOKEN_LINK;
161
3.66k
      }
162
4.83k
      break;
163
4.83k
    case 'm':
164
3.89k
      if (memeq("fro", name, 3)) {
165
684
        return NGHTTP2_TOKEN_FROM;
166
684
      }
167
3.20k
      break;
168
3.42k
    case 't':
169
3.42k
      if (memeq("hos", name, 3)) {
170
41
        return NGHTTP2_TOKEN_HOST;
171
41
      }
172
3.37k
      break;
173
5.34k
    case 'y':
174
5.34k
      if (memeq("var", name, 3)) {
175
2.77k
        return NGHTTP2_TOKEN_VARY;
176
2.77k
      }
177
2.56k
      break;
178
53.5k
    }
179
44.4k
    break;
180
44.4k
  case 5:
181
31.9k
    switch (name[4]) {
182
6.18k
    case 'e':
183
6.18k
      if (memeq("rang", name, 4)) {
184
1.13k
        return NGHTTP2_TOKEN_RANGE;
185
1.13k
      }
186
5.05k
      break;
187
10.2k
    case 'h':
188
10.2k
      if (memeq(":pat", name, 4)) {
189
8.35k
        return NGHTTP2_TOKEN__PATH;
190
8.35k
      }
191
1.84k
      break;
192
1.84k
    case 'w':
193
1.21k
      if (memeq("allo", name, 4)) {
194
400
        return NGHTTP2_TOKEN_ALLOW;
195
400
      }
196
815
      break;
197
31.9k
    }
198
22.0k
    break;
199
26.2k
  case 6:
200
26.2k
    switch (name[5]) {
201
3.20k
    case 'e':
202
3.20k
      if (memeq("cooki", name, 5)) {
203
1.99k
        return NGHTTP2_TOKEN_COOKIE;
204
1.99k
      }
205
1.21k
      break;
206
2.84k
    case 'r':
207
2.84k
      if (memeq("serve", name, 5)) {
208
601
        return NGHTTP2_TOKEN_SERVER;
209
601
      }
210
2.24k
      break;
211
13.1k
    case 't':
212
13.1k
      if (memeq("accep", name, 5)) {
213
9.11k
        return NGHTTP2_TOKEN_ACCEPT;
214
9.11k
      }
215
4.04k
      if (memeq("expec", name, 5)) {
216
1.64k
        return NGHTTP2_TOKEN_EXPECT;
217
1.64k
      }
218
2.40k
      break;
219
26.2k
    }
220
12.8k
    break;
221
42.2k
  case 7:
222
42.2k
    switch (name[6]) {
223
10.3k
    case 'd':
224
10.3k
      if (memeq(":metho", name, 6)) {
225
8.38k
        return NGHTTP2_TOKEN__METHOD;
226
8.38k
      }
227
1.95k
      break;
228
16.3k
    case 'e':
229
16.3k
      if (memeq(":schem", name, 6)) {
230
8.36k
        return NGHTTP2_TOKEN__SCHEME;
231
8.36k
      }
232
7.94k
      if (memeq("upgrad", name, 6)) {
233
104
        return NGHTTP2_TOKEN_UPGRADE;
234
104
      }
235
7.84k
      break;
236
7.84k
    case 'h':
237
795
      if (memeq("refres", name, 6)) {
238
331
        return NGHTTP2_TOKEN_REFRESH;
239
331
      }
240
464
      break;
241
6.71k
    case 'r':
242
6.71k
      if (memeq("refere", name, 6)) {
243
3.29k
        return NGHTTP2_TOKEN_REFERER;
244
3.29k
      }
245
3.42k
      break;
246
3.42k
    case 's':
247
1.50k
      if (memeq(":statu", name, 6)) {
248
10
        return NGHTTP2_TOKEN__STATUS;
249
10
      }
250
1.49k
      if (memeq("expire", name, 6)) {
251
337
        return NGHTTP2_TOKEN_EXPIRES;
252
337
      }
253
1.15k
      break;
254
42.2k
    }
255
21.4k
    break;
256
23.2k
  case 8:
257
23.2k
    switch (name[7]) {
258
3.38k
    case 'e':
259
3.38k
      if (memeq("if-rang", name, 7)) {
260
1.05k
        return NGHTTP2_TOKEN_IF_RANGE;
261
1.05k
      }
262
2.33k
      break;
263
3.57k
    case 'h':
264
3.57k
      if (memeq("if-matc", name, 7)) {
265
1.08k
        return NGHTTP2_TOKEN_IF_MATCH;
266
1.08k
      }
267
2.48k
      break;
268
3.05k
    case 'n':
269
3.05k
      if (memeq("locatio", name, 7)) {
270
1.38k
        return NGHTTP2_TOKEN_LOCATION;
271
1.38k
      }
272
1.67k
      break;
273
3.00k
    case 'y':
274
3.00k
      if (memeq("priorit", name, 7)) {
275
357
        return NGHTTP2_TOKEN_PRIORITY;
276
357
      }
277
2.64k
      break;
278
23.2k
    }
279
19.3k
    break;
280
19.3k
  case 9:
281
9.73k
    switch (name[8]) {
282
1.13k
    case 'l':
283
1.13k
      if (memeq(":protoco", name, 8)) {
284
46
        return NGHTTP2_TOKEN__PROTOCOL;
285
46
      }
286
1.08k
      break;
287
9.73k
    }
288
9.69k
    break;
289
31.4k
  case 10:
290
31.4k
    switch (name[9]) {
291
9.97k
    case 'e':
292
9.97k
      if (memeq("keep-aliv", name, 9)) {
293
21
        return NGHTTP2_TOKEN_KEEP_ALIVE;
294
21
      }
295
9.95k
      if (memeq("set-cooki", name, 9)) {
296
1.68k
        return NGHTTP2_TOKEN_SET_COOKIE;
297
1.68k
      }
298
8.26k
      break;
299
8.26k
    case 'n':
300
1.53k
      if (memeq("connectio", name, 9)) {
301
54
        return NGHTTP2_TOKEN_CONNECTION;
302
54
      }
303
1.48k
      break;
304
2.59k
    case 't':
305
2.59k
      if (memeq("user-agen", name, 9)) {
306
374
        return NGHTTP2_TOKEN_USER_AGENT;
307
374
      }
308
2.22k
      break;
309
12.2k
    case 'y':
310
12.2k
      if (memeq(":authorit", name, 9)) {
311
8.30k
        return NGHTTP2_TOKEN__AUTHORITY;
312
8.30k
      }
313
3.97k
      break;
314
31.4k
    }
315
20.9k
    break;
316
20.9k
  case 11:
317
11.1k
    switch (name[10]) {
318
1.51k
    case 'r':
319
1.51k
      if (memeq("retry-afte", name, 10)) {
320
826
        return NGHTTP2_TOKEN_RETRY_AFTER;
321
826
      }
322
685
      break;
323
11.1k
    }
324
10.3k
    break;
325
15.5k
  case 12:
326
15.5k
    switch (name[11]) {
327
8.40k
    case 'e':
328
8.40k
      if (memeq("content-typ", name, 11)) {
329
4.45k
        return NGHTTP2_TOKEN_CONTENT_TYPE;
330
4.45k
      }
331
3.95k
      break;
332
3.95k
    case 's':
333
2.57k
      if (memeq("max-forward", name, 11)) {
334
670
        return NGHTTP2_TOKEN_MAX_FORWARDS;
335
670
      }
336
1.90k
      break;
337
15.5k
    }
338
10.4k
    break;
339
19.4k
  case 13:
340
19.4k
    switch (name[12]) {
341
1.44k
    case 'd':
342
1.44k
      if (memeq("last-modifie", name, 12)) {
343
729
        return NGHTTP2_TOKEN_LAST_MODIFIED;
344
729
      }
345
718
      break;
346
2.67k
    case 'e':
347
2.67k
      if (memeq("content-rang", name, 12)) {
348
358
        return NGHTTP2_TOKEN_CONTENT_RANGE;
349
358
      }
350
2.31k
      break;
351
2.31k
    case 'h':
352
445
      if (memeq("if-none-matc", name, 12)) {
353
121
        return NGHTTP2_TOKEN_IF_NONE_MATCH;
354
121
      }
355
324
      break;
356
1.73k
    case 'l':
357
1.73k
      if (memeq("cache-contro", name, 12)) {
358
199
        return NGHTTP2_TOKEN_CACHE_CONTROL;
359
199
      }
360
1.53k
      break;
361
5.40k
    case 'n':
362
5.40k
      if (memeq("authorizatio", name, 12)) {
363
1.47k
        return NGHTTP2_TOKEN_AUTHORIZATION;
364
1.47k
      }
365
3.93k
      break;
366
3.93k
    case 's':
367
3.68k
      if (memeq("accept-range", name, 12)) {
368
1.47k
        return NGHTTP2_TOKEN_ACCEPT_RANGES;
369
1.47k
      }
370
2.21k
      break;
371
19.4k
    }
372
15.1k
    break;
373
15.1k
  case 14:
374
10.2k
    switch (name[13]) {
375
2.41k
    case 'h':
376
2.41k
      if (memeq("content-lengt", name, 13)) {
377
1.26k
        return NGHTTP2_TOKEN_CONTENT_LENGTH;
378
1.26k
      }
379
1.15k
      break;
380
3.77k
    case 't':
381
3.77k
      if (memeq("accept-charse", name, 13)) {
382
2.06k
        return NGHTTP2_TOKEN_ACCEPT_CHARSET;
383
2.06k
      }
384
1.71k
      break;
385
10.2k
    }
386
6.87k
    break;
387
8.83k
  case 15:
388
8.83k
    switch (name[14]) {
389
3.48k
    case 'e':
390
3.48k
      if (memeq("accept-languag", name, 14)) {
391
1.89k
        return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
392
1.89k
      }
393
1.58k
      break;
394
2.13k
    case 'g':
395
2.13k
      if (memeq("accept-encodin", name, 14)) {
396
1.31k
        return NGHTTP2_TOKEN_ACCEPT_ENCODING;
397
1.31k
      }
398
827
      break;
399
8.83k
    }
400
5.62k
    break;
401
12.6k
  case 16:
402
12.6k
    switch (name[15]) {
403
2.77k
    case 'e':
404
2.77k
      if (memeq("content-languag", name, 15)) {
405
600
        return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
406
600
      }
407
2.17k
      if (memeq("www-authenticat", name, 15)) {
408
911
        return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
409
911
      }
410
1.25k
      break;
411
2.45k
    case 'g':
412
2.45k
      if (memeq("content-encodin", name, 15)) {
413
545
        return NGHTTP2_TOKEN_CONTENT_ENCODING;
414
545
      }
415
1.90k
      break;
416
3.11k
    case 'n':
417
3.11k
      if (memeq("content-locatio", name, 15)) {
418
464
        return NGHTTP2_TOKEN_CONTENT_LOCATION;
419
464
      }
420
2.64k
      if (memeq("proxy-connectio", name, 15)) {
421
24
        return NGHTTP2_TOKEN_PROXY_CONNECTION;
422
24
      }
423
2.62k
      break;
424
12.6k
    }
425
10.1k
    break;
426
10.1k
  case 17:
427
8.73k
    switch (name[16]) {
428
3.47k
    case 'e':
429
3.47k
      if (memeq("if-modified-sinc", name, 16)) {
430
1.12k
        return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
431
1.12k
      }
432
2.35k
      break;
433
2.35k
    case 'g':
434
978
      if (memeq("transfer-encodin", name, 16)) {
435
25
        return NGHTTP2_TOKEN_TRANSFER_ENCODING;
436
25
      }
437
953
      break;
438
8.73k
    }
439
7.58k
    break;
440
7.58k
  case 18:
441
4.04k
    switch (name[17]) {
442
1.88k
    case 'e':
443
1.88k
      if (memeq("proxy-authenticat", name, 17)) {
444
173
        return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
445
173
      }
446
1.71k
      break;
447
4.04k
    }
448
3.86k
    break;
449
10.3k
  case 19:
450
10.3k
    switch (name[18]) {
451
3.63k
    case 'e':
452
3.63k
      if (memeq("if-unmodified-sinc", name, 18)) {
453
492
        return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
454
492
      }
455
3.13k
      break;
456
5.25k
    case 'n':
457
5.25k
      if (memeq("content-dispositio", name, 18)) {
458
826
        return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
459
826
      }
460
4.42k
      if (memeq("proxy-authorizatio", name, 18)) {
461
675
        return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
462
675
      }
463
3.75k
      break;
464
10.3k
    }
465
8.40k
    break;
466
8.40k
  case 25:
467
4.00k
    switch (name[24]) {
468
451
    case 'y':
469
451
      if (memeq("strict-transport-securit", name, 24)) {
470
198
        return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
471
198
      }
472
253
      break;
473
4.00k
    }
474
3.81k
    break;
475
3.81k
  case 27:
476
2.22k
    switch (name[26]) {
477
1.66k
    case 'n':
478
1.66k
      if (memeq("access-control-allow-origi", name, 26)) {
479
746
        return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
480
746
      }
481
922
      break;
482
2.22k
    }
483
1.47k
    break;
484
465k
  }
485
367k
  return -1;
486
465k
}
487
488
159k
void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
489
159k
  ent->nv = *nv;
490
159k
  ent->cnv.name = nv->name->base;
491
159k
  ent->cnv.namelen = nv->name->len;
492
159k
  ent->cnv.value = nv->value->base;
493
159k
  ent->cnv.valuelen = nv->value->len;
494
159k
  ent->cnv.flags = nv->flags;
495
159k
  ent->next = NULL;
496
159k
  ent->hash = 0;
497
498
159k
  nghttp2_rcbuf_incref(ent->nv.name);
499
159k
  nghttp2_rcbuf_incref(ent->nv.value);
500
159k
}
501
502
159k
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
503
159k
  nghttp2_rcbuf_decref(ent->nv.value);
504
159k
  nghttp2_rcbuf_decref(ent->nv.name);
505
159k
}
506
507
381k
static int name_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
508
381k
  return a->name->len == b->namelen &&
509
381k
         memeq(a->name->base, b->name, b->namelen);
510
381k
}
511
512
437k
static int value_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
513
437k
  return a->value->len == b->valuelen &&
514
437k
         memeq(a->value->base, b->value, b->valuelen);
515
437k
}
516
517
358k
static uint32_t name_hash(const nghttp2_nv *nv) {
518
  /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
519
358k
  uint32_t h = 2166136261u;
520
358k
  size_t i;
521
522
4.22M
  for (i = 0; i < nv->namelen; ++i) {
523
3.86M
    h ^= nv->name[i];
524
3.86M
    h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
525
3.86M
  }
526
527
358k
  return h;
528
358k
}
529
530
8.35k
static void hd_map_init(nghttp2_hd_map *map) {
531
8.35k
  memset(map, 0, sizeof(nghttp2_hd_map));
532
8.35k
}
533
534
152k
static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
535
152k
  nghttp2_hd_entry **bucket;
536
537
152k
  bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
538
539
152k
  if (*bucket == NULL) {
540
94.6k
    *bucket = ent;
541
94.6k
    return;
542
94.6k
  }
543
544
  /* lower index is linked near the root */
545
57.9k
  ent->next = *bucket;
546
57.9k
  *bucket = ent;
547
57.9k
}
548
549
static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
550
                                     const nghttp2_nv *nv, int32_t token,
551
456k
                                     uint32_t hash, int name_only) {
552
456k
  nghttp2_hd_entry *p;
553
456k
  nghttp2_hd_entry *res = NULL;
554
555
456k
  *exact_match = 0;
556
557
775k
  for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) {
558
569k
    if (token != p->nv.token ||
559
569k
        (token == -1 && (hash != p->hash || !name_eq(&p->nv, nv)))) {
560
131k
      continue;
561
131k
    }
562
438k
    if (!res) {
563
283k
      res = p;
564
283k
      if (name_only) {
565
548
        break;
566
548
      }
567
283k
    }
568
437k
    if (value_eq(&p->nv, nv)) {
569
250k
      res = p;
570
250k
      *exact_match = 1;
571
250k
      break;
572
250k
    }
573
437k
  }
574
575
456k
  return res;
576
456k
}
577
578
88.5k
static void hd_map_remove(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
579
88.5k
  nghttp2_hd_entry **dst;
580
581
88.5k
  dst = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
582
583
176k
  for (; *dst; dst = &(*dst)->next) {
584
176k
    if (*dst != ent) {
585
87.9k
      continue;
586
87.9k
    }
587
588
88.5k
    *dst = ent->next;
589
88.5k
    ent->next = NULL;
590
88.5k
    return;
591
176k
  }
592
88.5k
}
593
594
static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
595
16.7k
                           nghttp2_mem *mem) {
596
16.7k
  size_t size;
597
133k
  for (size = 1; size < bufsize; size <<= 1)
598
116k
    ;
599
16.7k
  ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
600
16.7k
  if (ringbuf->buffer == NULL) {
601
0
    return NGHTTP2_ERR_NOMEM;
602
0
  }
603
16.7k
  ringbuf->mask = size - 1;
604
16.7k
  ringbuf->first = 0;
605
16.7k
  ringbuf->len = 0;
606
16.7k
  return 0;
607
16.7k
}
608
609
static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
610
328k
                                        size_t idx) {
611
328k
  assert(idx < ringbuf->len);
612
328k
  return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
613
328k
}
614
615
static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
616
159k
                              nghttp2_mem *mem) {
617
159k
  size_t i;
618
159k
  size_t size;
619
159k
  nghttp2_hd_entry **buffer;
620
621
159k
  if (ringbuf->mask + 1 >= bufsize) {
622
159k
    return 0;
623
159k
  }
624
0
  for (size = 1; size < bufsize; size <<= 1)
625
0
    ;
626
0
  buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
627
0
  if (buffer == NULL) {
628
0
    return NGHTTP2_ERR_NOMEM;
629
0
  }
630
0
  for (i = 0; i < ringbuf->len; ++i) {
631
0
    buffer[i] = hd_ringbuf_get(ringbuf, i);
632
0
  }
633
0
  nghttp2_mem_free(mem, ringbuf->buffer);
634
0
  ringbuf->buffer = buffer;
635
0
  ringbuf->mask = size - 1;
636
0
  ringbuf->first = 0;
637
0
  return 0;
638
0
}
639
640
16.7k
static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
641
16.7k
  size_t i;
642
16.7k
  if (ringbuf == NULL) {
643
0
    return;
644
0
  }
645
86.7k
  for (i = 0; i < ringbuf->len; ++i) {
646
70.0k
    nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
647
648
70.0k
    nghttp2_hd_entry_free(ent);
649
70.0k
    nghttp2_mem_free(mem, ent);
650
70.0k
  }
651
16.7k
  nghttp2_mem_free(mem, ringbuf->buffer);
652
16.7k
}
653
654
static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
655
159k
                                 nghttp2_hd_entry *ent, nghttp2_mem *mem) {
656
159k
  int rv;
657
658
159k
  rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
659
660
159k
  if (rv != 0) {
661
0
    return rv;
662
0
  }
663
664
159k
  ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
665
159k
  ++ringbuf->len;
666
667
159k
  return 0;
668
159k
}
669
670
89.0k
static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
671
89.0k
  assert(ringbuf->len > 0);
672
89.0k
  --ringbuf->len;
673
89.0k
}
674
675
16.7k
static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
676
16.7k
  int rv;
677
16.7k
  context->mem = mem;
678
16.7k
  context->bad = 0;
679
16.7k
  context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
680
16.7k
  rv = hd_ringbuf_init(
681
16.7k
      &context->hd_table,
682
16.7k
      context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
683
16.7k
  if (rv != 0) {
684
0
    return rv;
685
0
  }
686
687
16.7k
  context->hd_table_bufsize = 0;
688
16.7k
  context->next_seq = 0;
689
690
16.7k
  return 0;
691
16.7k
}
692
693
16.7k
static void hd_context_free(nghttp2_hd_context *context) {
694
16.7k
  hd_ringbuf_free(&context->hd_table, context->mem);
695
16.7k
}
696
697
0
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
698
0
  return nghttp2_hd_deflate_init2(
699
0
      deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
700
0
}
701
702
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
703
                             size_t max_deflate_dynamic_table_size,
704
8.35k
                             nghttp2_mem *mem) {
705
8.35k
  int rv;
706
8.35k
  rv = hd_context_init(&deflater->ctx, mem);
707
8.35k
  if (rv != 0) {
708
0
    return rv;
709
0
  }
710
711
8.35k
  hd_map_init(&deflater->map);
712
713
8.35k
  if (max_deflate_dynamic_table_size < NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE) {
714
0
    deflater->notify_table_size_change = 1;
715
0
    deflater->ctx.hd_table_bufsize_max = max_deflate_dynamic_table_size;
716
8.35k
  } else {
717
8.35k
    deflater->notify_table_size_change = 0;
718
8.35k
  }
719
720
8.35k
  deflater->deflate_hd_table_bufsize_max = max_deflate_dynamic_table_size;
721
8.35k
  deflater->min_hd_table_bufsize_max = UINT32_MAX;
722
723
8.35k
  return 0;
724
8.35k
}
725
726
8.35k
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
727
8.35k
  int rv;
728
729
8.35k
  rv = hd_context_init(&inflater->ctx, mem);
730
8.35k
  if (rv != 0) {
731
0
    goto fail;
732
0
  }
733
734
8.35k
  inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
735
8.35k
  inflater->min_hd_table_bufsize_max = UINT32_MAX;
736
737
8.35k
  inflater->nv_name_keep = NULL;
738
8.35k
  inflater->nv_value_keep = NULL;
739
740
8.35k
  inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
741
8.35k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
742
743
8.35k
  nghttp2_buf_init(&inflater->namebuf);
744
8.35k
  nghttp2_buf_init(&inflater->valuebuf);
745
746
8.35k
  inflater->namercbuf = NULL;
747
8.35k
  inflater->valuercbuf = NULL;
748
749
8.35k
  inflater->huffman_encoded = 0;
750
8.35k
  inflater->index = 0;
751
8.35k
  inflater->left = 0;
752
8.35k
  inflater->shift = 0;
753
8.35k
  inflater->index_required = 0;
754
8.35k
  inflater->no_index = 0;
755
756
8.35k
  return 0;
757
758
0
fail:
759
0
  return rv;
760
8.35k
}
761
762
217k
static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
763
217k
  nghttp2_rcbuf_decref(inflater->nv_value_keep);
764
217k
  nghttp2_rcbuf_decref(inflater->nv_name_keep);
765
766
217k
  inflater->nv_value_keep = NULL;
767
217k
  inflater->nv_name_keep = NULL;
768
217k
}
769
770
8.35k
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
771
8.35k
  hd_context_free(&deflater->ctx);
772
8.35k
}
773
774
8.35k
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
775
8.35k
  hd_inflate_keep_free(inflater);
776
777
8.35k
  nghttp2_rcbuf_decref(inflater->valuercbuf);
778
8.35k
  nghttp2_rcbuf_decref(inflater->namercbuf);
779
780
8.35k
  hd_context_free(&inflater->ctx);
781
8.35k
}
782
783
686k
static size_t entry_room(size_t namelen, size_t valuelen) {
784
686k
  return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
785
686k
}
786
787
203k
static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
788
203k
  DEBUGF("inflatehd: header emission: %s: %s\n", nv->name->base,
789
203k
         nv->value->base);
790
  /* ent->ref may be 0. This happens if the encoder emits literal
791
     block larger than header table capacity with indexing. */
792
203k
  *nv_out = *nv;
793
203k
}
794
795
622k
static size_t count_encoded_length(size_t n, size_t prefix) {
796
622k
  size_t k = (size_t)((1 << prefix) - 1);
797
622k
  size_t len = 0;
798
799
622k
  if (n < k) {
800
571k
    return 1;
801
571k
  }
802
803
50.5k
  n -= k;
804
50.5k
  ++len;
805
806
51.8k
  for (; n >= 128; n >>= 7, ++len)
807
1.33k
    ;
808
809
50.5k
  return len + 1;
810
622k
}
811
812
622k
static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
813
622k
  size_t k = (size_t)((1 << prefix) - 1);
814
622k
  uint8_t *begin = buf;
815
816
622k
  *buf = (uint8_t)(*buf & ~k);
817
818
622k
  if (n < k) {
819
571k
    *buf = (uint8_t)(*buf | n);
820
571k
    return 1;
821
571k
  }
822
823
50.5k
  *buf = (uint8_t)(*buf | k);
824
50.5k
  ++buf;
825
826
50.5k
  n -= k;
827
828
51.8k
  for (; n >= 128; n >>= 7) {
829
1.33k
    *buf++ = (uint8_t)((1 << 7) | (n & 0x7f));
830
1.33k
  }
831
832
50.5k
  *buf++ = (uint8_t)n;
833
834
50.5k
  return (size_t)(buf - begin);
835
622k
}
836
837
/*
838
 * Decodes |prefix| prefixed integer stored from |in|.  The |last|
839
 * represents the 1 beyond the last of the valid contiguous memory
840
 * region from |in|.  The decoded integer must be less than or equal
841
 * to UINT32_MAX.
842
 *
843
 * If the |initial| is nonzero, it is used as a initial value, this
844
 * function assumes the |in| starts with intermediate data.
845
 *
846
 * An entire integer is decoded successfully, decoded, the |*fin| is
847
 * set to nonzero.
848
 *
849
 * This function stores the decoded integer in |*res| if it succeed,
850
 * including partial decoding (in this case, number of shift to make
851
 * in the next call will be stored in |*shift_ptr|) and returns number
852
 * of bytes processed, or returns -1, indicating decoding error.
853
 */
854
static nghttp2_ssize decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
855
                                   uint32_t initial, size_t shift,
856
                                   const uint8_t *in, const uint8_t *last,
857
225k
                                   size_t prefix) {
858
225k
  uint32_t k = (uint8_t)((1 << prefix) - 1);
859
225k
  uint32_t n = initial;
860
225k
  const uint8_t *start = in;
861
862
225k
  *shift_ptr = 0;
863
225k
  *fin = 0;
864
865
225k
  if (n == 0) {
866
225k
    if ((*in & k) != k) {
867
224k
      *res = (*in) & k;
868
224k
      *fin = 1;
869
224k
      return 1;
870
224k
    }
871
872
1.51k
    n = k;
873
874
1.51k
    if (++in == last) {
875
87
      *res = n;
876
87
      return (nghttp2_ssize)(in - start);
877
87
    }
878
1.51k
  }
879
880
2.80k
  for (; in != last; ++in, shift += 7) {
881
2.62k
    uint32_t add = *in & 0x7f;
882
883
2.62k
    if (shift >= 32) {
884
15
      DEBUGF("inflate: shift exponent overflow\n");
885
15
      return -1;
886
15
    }
887
888
2.60k
    if ((UINT32_MAX >> shift) < add) {
889
57
      DEBUGF("inflate: integer overflow on shift\n");
890
57
      return -1;
891
57
    }
892
893
2.54k
    add <<= shift;
894
895
2.54k
    if (UINT32_MAX - add < n) {
896
8
      DEBUGF("inflate: integer overflow on addition\n");
897
8
      return -1;
898
8
    }
899
900
2.54k
    n += add;
901
902
2.54k
    if ((*in & (1 << 7)) == 0) {
903
1.32k
      break;
904
1.32k
    }
905
2.54k
  }
906
907
1.50k
  *shift_ptr = shift;
908
909
1.50k
  if (in == last) {
910
182
    *res = n;
911
182
    return (nghttp2_ssize)(in - start);
912
182
  }
913
914
1.32k
  *res = n;
915
1.32k
  *fin = 1;
916
1.32k
  return (nghttp2_ssize)(in + 1 - start);
917
1.50k
}
918
919
196
static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
920
196
  int rv;
921
196
  uint8_t *bufp;
922
196
  size_t blocklen;
923
196
  uint8_t sb[16];
924
925
196
  DEBUGF("deflatehd: emit table_size=%zu\n", table_size);
926
927
196
  blocklen = count_encoded_length(table_size, 5);
928
929
196
  if (sizeof(sb) < blocklen) {
930
0
    return NGHTTP2_ERR_HEADER_COMP;
931
0
  }
932
933
196
  bufp = sb;
934
935
196
  *bufp = 0x20u;
936
937
196
  encode_length(bufp, table_size, 5);
938
939
196
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
940
196
  if (rv != 0) {
941
0
    return rv;
942
0
  }
943
944
196
  return 0;
945
196
}
946
947
291k
static int emit_indexed_block(nghttp2_bufs *bufs, size_t idx) {
948
291k
  int rv;
949
291k
  size_t blocklen;
950
291k
  uint8_t sb[16];
951
291k
  uint8_t *bufp;
952
953
291k
  blocklen = count_encoded_length(idx + 1, 7);
954
955
291k
  DEBUGF("deflatehd: emit indexed index=%zu, %zu bytes\n", idx, blocklen);
956
957
291k
  if (sizeof(sb) < blocklen) {
958
0
    return NGHTTP2_ERR_HEADER_COMP;
959
0
  }
960
961
291k
  bufp = sb;
962
291k
  *bufp = 0x80u;
963
291k
  encode_length(bufp, idx + 1, 7);
964
965
291k
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
966
291k
  if (rv != 0) {
967
0
    return rv;
968
0
  }
969
970
291k
  return 0;
971
291k
}
972
973
270k
static int emit_string(nghttp2_bufs *bufs, const uint8_t *str, size_t len) {
974
270k
  int rv;
975
270k
  uint8_t sb[16];
976
270k
  uint8_t *bufp;
977
270k
  size_t blocklen;
978
270k
  size_t enclen;
979
270k
  int huffman = 0;
980
981
270k
  enclen = nghttp2_hd_huff_encode_count(str, len);
982
983
270k
  if (enclen < len) {
984
64.1k
    huffman = 1;
985
206k
  } else {
986
206k
    enclen = len;
987
206k
  }
988
989
270k
  blocklen = count_encoded_length(enclen, 7);
990
991
270k
  DEBUGF("deflatehd: emit string str=%.*s, length=%zu, huffman=%d, "
992
270k
         "encoded_length=%zu\n",
993
270k
         (int)len, (const char *)str, len, huffman, enclen);
994
995
270k
  if (sizeof(sb) < blocklen) {
996
0
    return NGHTTP2_ERR_HEADER_COMP;
997
0
  }
998
999
270k
  bufp = sb;
1000
270k
  *bufp = huffman ? 1 << 7 : 0;
1001
270k
  encode_length(bufp, enclen, 7);
1002
1003
270k
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1004
270k
  if (rv != 0) {
1005
0
    return rv;
1006
0
  }
1007
1008
270k
  if (huffman) {
1009
64.1k
    rv = nghttp2_hd_huff_encode(bufs, str, len);
1010
206k
  } else {
1011
206k
    assert(enclen == len);
1012
206k
    rv = nghttp2_bufs_add(bufs, str, len);
1013
206k
  }
1014
1015
270k
  return rv;
1016
270k
}
1017
1018
165k
static uint8_t pack_first_byte(int indexing_mode) {
1019
165k
  switch (indexing_mode) {
1020
152k
  case NGHTTP2_HD_WITH_INDEXING:
1021
152k
    return 0x40u;
1022
9.57k
  case NGHTTP2_HD_WITHOUT_INDEXING:
1023
9.57k
    return 0;
1024
3.09k
  case NGHTTP2_HD_NEVER_INDEXING:
1025
3.09k
    return 0x10u;
1026
0
  default:
1027
0
    assert(0);
1028
165k
  }
1029
  /* This is required to compile with android NDK r10d +
1030
     --enable-werror */
1031
0
  return 0;
1032
165k
}
1033
1034
static int emit_indname_block(nghttp2_bufs *bufs, size_t idx,
1035
59.5k
                              const nghttp2_nv *nv, int indexing_mode) {
1036
59.5k
  int rv;
1037
59.5k
  uint8_t *bufp;
1038
59.5k
  size_t blocklen;
1039
59.5k
  uint8_t sb[16];
1040
59.5k
  size_t prefixlen;
1041
1042
59.5k
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1043
49.4k
    prefixlen = 6;
1044
49.4k
  } else {
1045
10.1k
    prefixlen = 4;
1046
10.1k
  }
1047
1048
59.5k
  DEBUGF("deflatehd: emit indname index=%zu, valuelen=%zu, indexing_mode=%d\n",
1049
59.5k
         idx, nv->valuelen, indexing_mode);
1050
1051
59.5k
  blocklen = count_encoded_length(idx + 1, prefixlen);
1052
1053
59.5k
  if (sizeof(sb) < blocklen) {
1054
0
    return NGHTTP2_ERR_HEADER_COMP;
1055
0
  }
1056
1057
59.5k
  bufp = sb;
1058
1059
59.5k
  *bufp = pack_first_byte(indexing_mode);
1060
1061
59.5k
  encode_length(bufp, idx + 1, prefixlen);
1062
1063
59.5k
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1064
59.5k
  if (rv != 0) {
1065
0
    return rv;
1066
0
  }
1067
1068
59.5k
  rv = emit_string(bufs, nv->value, nv->valuelen);
1069
59.5k
  if (rv != 0) {
1070
0
    return rv;
1071
0
  }
1072
1073
59.5k
  return 0;
1074
59.5k
}
1075
1076
static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
1077
105k
                              int indexing_mode) {
1078
105k
  int rv;
1079
1080
105k
  DEBUGF(
1081
105k
      "deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
1082
105k
      nv->namelen, nv->valuelen, indexing_mode);
1083
1084
105k
  rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
1085
105k
  if (rv != 0) {
1086
0
    return rv;
1087
0
  }
1088
1089
105k
  rv = emit_string(bufs, nv->name, nv->namelen);
1090
105k
  if (rv != 0) {
1091
0
    return rv;
1092
0
  }
1093
1094
105k
  rv = emit_string(bufs, nv->value, nv->valuelen);
1095
105k
  if (rv != 0) {
1096
0
    return rv;
1097
0
  }
1098
1099
105k
  return 0;
1100
105k
}
1101
1102
static int add_hd_table_incremental(nghttp2_hd_context *context,
1103
                                    nghttp2_hd_nv *nv, nghttp2_hd_map *map,
1104
159k
                                    uint32_t hash) {
1105
159k
  int rv;
1106
159k
  nghttp2_hd_entry *new_ent;
1107
159k
  size_t room;
1108
159k
  nghttp2_mem *mem;
1109
1110
159k
  mem = context->mem;
1111
159k
  room = entry_room(nv->name->len, nv->value->len);
1112
1113
246k
  while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
1114
246k
         context->hd_table.len > 0) {
1115
1116
86.8k
    size_t idx = context->hd_table.len - 1;
1117
86.8k
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1118
1119
86.8k
    context->hd_table_bufsize -=
1120
86.8k
        entry_room(ent->nv.name->len, ent->nv.value->len);
1121
1122
86.8k
    DEBUGF("hpack: remove item from header table: %s: %s\n",
1123
86.8k
           (char *)ent->nv.name->base, (char *)ent->nv.value->base);
1124
1125
86.8k
    hd_ringbuf_pop_back(&context->hd_table);
1126
86.8k
    if (map) {
1127
86.4k
      hd_map_remove(map, ent);
1128
86.4k
    }
1129
1130
86.8k
    nghttp2_hd_entry_free(ent);
1131
86.8k
    nghttp2_mem_free(mem, ent);
1132
86.8k
  }
1133
1134
159k
  if (room > context->hd_table_bufsize_max) {
1135
    /* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is
1136
       immediately evicted.  So we don't allocate memory for it. */
1137
452
    return 0;
1138
452
  }
1139
1140
159k
  new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
1141
159k
  if (new_ent == NULL) {
1142
0
    return NGHTTP2_ERR_NOMEM;
1143
0
  }
1144
1145
159k
  nghttp2_hd_entry_init(new_ent, nv);
1146
1147
159k
  rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
1148
1149
159k
  if (rv != 0) {
1150
0
    nghttp2_hd_entry_free(new_ent);
1151
0
    nghttp2_mem_free(mem, new_ent);
1152
1153
0
    return rv;
1154
0
  }
1155
1156
159k
  new_ent->seq = context->next_seq++;
1157
159k
  new_ent->hash = hash;
1158
1159
159k
  if (map) {
1160
152k
    hd_map_insert(map, new_ent);
1161
152k
  }
1162
1163
159k
  context->hd_table_bufsize += room;
1164
1165
159k
  return 0;
1166
159k
}
1167
1168
typedef struct {
1169
  nghttp2_ssize index;
1170
  /* Nonzero if both name and value are matched. */
1171
  int name_value_match;
1172
} search_result;
1173
1174
static search_result search_static_table(const nghttp2_nv *nv, int32_t token,
1175
78.3k
                                         int name_only) {
1176
78.3k
  search_result res = {token, 0};
1177
78.3k
  int i;
1178
78.3k
  const nghttp2_hd_static_entry *ent;
1179
1180
78.3k
  if (name_only) {
1181
3.09k
    return res;
1182
3.09k
  }
1183
1184
75.2k
  for (i = token;
1185
112k
       i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token;
1186
78.0k
       ++i) {
1187
78.0k
    ent = &static_table[i];
1188
78.0k
    if (ent->value.len == nv->valuelen &&
1189
78.0k
        memcmp(ent->value.base, nv->value, nv->valuelen) == 0) {
1190
41.1k
      res.index = i;
1191
41.1k
      res.name_value_match = 1;
1192
41.1k
      return res;
1193
41.1k
    }
1194
78.0k
  }
1195
34.1k
  return res;
1196
75.2k
}
1197
1198
static search_result search_hd_table(nghttp2_hd_context *context,
1199
                                     const nghttp2_nv *nv, int32_t token,
1200
                                     int indexing_mode, nghttp2_hd_map *map,
1201
456k
                                     uint32_t hash) {
1202
456k
  search_result res = {-1, 0};
1203
456k
  const nghttp2_hd_entry *ent;
1204
456k
  int exact_match;
1205
456k
  int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
1206
1207
456k
  exact_match = 0;
1208
456k
  ent = hd_map_find(map, &exact_match, nv, token, hash, name_only);
1209
1210
456k
  if (!exact_match && token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1211
78.3k
    return search_static_table(nv, token, name_only);
1212
78.3k
  }
1213
1214
378k
  if (ent == NULL) {
1215
105k
    return res;
1216
105k
  }
1217
1218
272k
  res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq +
1219
272k
                              NGHTTP2_STATIC_TABLE_LENGTH);
1220
272k
  res.name_value_match = exact_match;
1221
1222
272k
  return res;
1223
378k
}
1224
1225
static void hd_context_shrink_table_size(nghttp2_hd_context *context,
1226
2.83k
                                         nghttp2_hd_map *map) {
1227
2.83k
  nghttp2_mem *mem;
1228
1229
2.83k
  mem = context->mem;
1230
1231
5.02k
  while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
1232
5.02k
         context->hd_table.len > 0) {
1233
2.18k
    size_t idx = context->hd_table.len - 1;
1234
2.18k
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1235
2.18k
    context->hd_table_bufsize -=
1236
2.18k
        entry_room(ent->nv.name->len, ent->nv.value->len);
1237
2.18k
    hd_ringbuf_pop_back(&context->hd_table);
1238
2.18k
    if (map) {
1239
2.16k
      hd_map_remove(map, ent);
1240
2.16k
    }
1241
1242
2.18k
    nghttp2_hd_entry_free(ent);
1243
2.18k
    nghttp2_mem_free(mem, ent);
1244
2.18k
  }
1245
2.83k
}
1246
1247
int nghttp2_hd_deflate_change_table_size(
1248
1.26k
    nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
1249
1.26k
  size_t next_bufsize = nghttp2_min_size(
1250
1.26k
      settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
1251
1252
1.26k
  deflater->ctx.hd_table_bufsize_max = next_bufsize;
1253
1254
1.26k
  deflater->min_hd_table_bufsize_max =
1255
1.26k
      nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
1256
1257
1.26k
  deflater->notify_table_size_change = 1;
1258
1259
1.26k
  hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
1260
1.26k
  return 0;
1261
1.26k
}
1262
1263
int nghttp2_hd_inflate_change_table_size(
1264
0
    nghttp2_hd_inflater *inflater, size_t settings_max_dynamic_table_size) {
1265
0
  switch (inflater->state) {
1266
0
  case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1267
0
  case NGHTTP2_HD_STATE_INFLATE_START:
1268
0
    break;
1269
0
  default:
1270
0
    return NGHTTP2_ERR_INVALID_STATE;
1271
0
  }
1272
1273
0
  inflater->settings_hd_table_bufsize_max = settings_max_dynamic_table_size;
1274
1275
  /* It seems that encoder is not required to send dynamic table size
1276
     update if the table size is not changed after applying
1277
     SETTINGS_HEADER_TABLE_SIZE.  RFC 7541 is ambiguous here, but this
1278
     is the intention of the editor.  If new maximum table size is
1279
     strictly smaller than the current negotiated maximum size,
1280
     encoder must send dynamic table size update.  In other cases, we
1281
     cannot expect it to do so. */
1282
0
  if (inflater->ctx.hd_table_bufsize_max > settings_max_dynamic_table_size) {
1283
0
    inflater->state = NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE;
1284
    /* Remember minimum value, and validate that encoder sends the
1285
       value less than or equal to this. */
1286
0
    inflater->min_hd_table_bufsize_max = settings_max_dynamic_table_size;
1287
1288
0
    inflater->ctx.hd_table_bufsize_max = settings_max_dynamic_table_size;
1289
1290
0
    hd_context_shrink_table_size(&inflater->ctx, NULL);
1291
0
  }
1292
1293
0
  return 0;
1294
0
}
1295
1296
#define INDEX_RANGE_VALID(context, idx)                                        \
1297
0
  ((idx) < (context)->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH)
1298
1299
195k
static size_t get_max_index(nghttp2_hd_context *context) {
1300
195k
  return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
1301
195k
}
1302
1303
243k
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
1304
243k
  assert(INDEX_RANGE_VALID(context, idx));
1305
243k
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1306
169k
    return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
1307
169k
        ->nv;
1308
169k
  } else {
1309
74.1k
    const nghttp2_hd_static_entry *ent = &static_table[idx];
1310
74.1k
    nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name,
1311
74.1k
                        (nghttp2_rcbuf *)&ent->value, ent->token,
1312
74.1k
                        NGHTTP2_NV_FLAG_NONE};
1313
74.1k
    return nv;
1314
74.1k
  }
1315
243k
}
1316
1317
static const nghttp2_nv *nghttp2_hd_table_get2(nghttp2_hd_context *context,
1318
0
                                               size_t idx) {
1319
0
  assert(INDEX_RANGE_VALID(context, idx));
1320
0
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1321
0
    return &hd_ringbuf_get(&context->hd_table,
1322
0
                           idx - NGHTTP2_STATIC_TABLE_LENGTH)
1323
0
                ->cnv;
1324
0
  }
1325
1326
0
  return &static_table[idx].cnv;
1327
0
}
1328
1329
static int hd_deflate_decide_indexing(nghttp2_hd_deflater *deflater,
1330
453k
                                      const nghttp2_nv *nv, int32_t token) {
1331
453k
  if (token == NGHTTP2_TOKEN__PATH || token == NGHTTP2_TOKEN_AGE ||
1332
453k
      token == NGHTTP2_TOKEN_CONTENT_LENGTH || token == NGHTTP2_TOKEN_ETAG ||
1333
453k
      token == NGHTTP2_TOKEN_IF_MODIFIED_SINCE ||
1334
453k
      token == NGHTTP2_TOKEN_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION ||
1335
453k
      token == NGHTTP2_TOKEN_SET_COOKIE ||
1336
453k
      entry_room(nv->namelen, nv->valuelen) >
1337
438k
          deflater->ctx.hd_table_bufsize_max * 3 / 4) {
1338
18.3k
    return NGHTTP2_HD_WITHOUT_INDEXING;
1339
18.3k
  }
1340
1341
435k
  return NGHTTP2_HD_WITH_INDEXING;
1342
453k
}
1343
1344
static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
1345
456k
                      const nghttp2_nv *nv) {
1346
456k
  int rv;
1347
456k
  search_result res;
1348
456k
  nghttp2_ssize idx;
1349
456k
  int indexing_mode;
1350
456k
  int32_t token;
1351
456k
  nghttp2_mem *mem;
1352
456k
  uint32_t hash = 0;
1353
1354
456k
  DEBUGF("deflatehd: deflating %.*s: %.*s\n", (int)nv->namelen, nv->name,
1355
456k
         (int)nv->valuelen, nv->value);
1356
1357
456k
  mem = deflater->ctx.mem;
1358
1359
456k
  token = lookup_token(nv->name, nv->namelen);
1360
456k
  if (token == -1) {
1361
358k
    hash = name_hash(nv);
1362
358k
  } else if (token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1363
95.3k
    hash = static_table[token].hash;
1364
95.3k
  }
1365
1366
  /* Don't index authorization header field since it may contain low
1367
     entropy secret data (e.g., id/password).  Also cookie header
1368
     field with less than 20 bytes value is also never indexed.  This
1369
     is the same criteria used in Firefox codebase. */
1370
456k
  indexing_mode =
1371
456k
      token == NGHTTP2_TOKEN_AUTHORIZATION ||
1372
456k
              (token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
1373
456k
              (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
1374
456k
          ? NGHTTP2_HD_NEVER_INDEXING
1375
456k
          : hd_deflate_decide_indexing(deflater, nv, token);
1376
1377
456k
  res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
1378
456k
                        &deflater->map, hash);
1379
1380
456k
  idx = res.index;
1381
1382
456k
  if (res.name_value_match) {
1383
1384
291k
    DEBUGF("deflatehd: name/value match index=%td\n", idx);
1385
1386
291k
    rv = emit_indexed_block(bufs, (size_t)idx);
1387
291k
    if (rv != 0) {
1388
0
      return rv;
1389
0
    }
1390
1391
291k
    return 0;
1392
291k
  }
1393
1394
165k
  if (res.index != -1) {
1395
59.5k
    DEBUGF("deflatehd: name match index=%td\n", res.index);
1396
59.5k
  }
1397
1398
165k
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1399
152k
    nghttp2_hd_nv hd_nv;
1400
1401
152k
    if (idx != -1) {
1402
49.4k
      hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
1403
49.4k
      nghttp2_rcbuf_incref(hd_nv.name);
1404
103k
    } else {
1405
103k
      rv = nghttp2_rcbuf_new2(&hd_nv.name, nv->name, nv->namelen, mem);
1406
103k
      if (rv != 0) {
1407
0
        return rv;
1408
0
      }
1409
103k
    }
1410
1411
152k
    rv = nghttp2_rcbuf_new2(&hd_nv.value, nv->value, nv->valuelen, mem);
1412
1413
152k
    if (rv != 0) {
1414
0
      nghttp2_rcbuf_decref(hd_nv.name);
1415
0
      return rv;
1416
0
    }
1417
1418
152k
    hd_nv.token = token;
1419
152k
    hd_nv.flags = NGHTTP2_NV_FLAG_NONE;
1420
1421
152k
    rv = add_hd_table_incremental(&deflater->ctx, &hd_nv, &deflater->map, hash);
1422
1423
152k
    nghttp2_rcbuf_decref(hd_nv.value);
1424
152k
    nghttp2_rcbuf_decref(hd_nv.name);
1425
1426
152k
    if (rv != 0) {
1427
0
      return NGHTTP2_ERR_HEADER_COMP;
1428
0
    }
1429
152k
  }
1430
165k
  if (idx == -1) {
1431
105k
    rv = emit_newname_block(bufs, nv, indexing_mode);
1432
105k
  } else {
1433
59.5k
    rv = emit_indname_block(bufs, (size_t)idx, nv, indexing_mode);
1434
59.5k
  }
1435
165k
  if (rv != 0) {
1436
0
    return rv;
1437
0
  }
1438
1439
165k
  return 0;
1440
165k
}
1441
1442
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
1443
                               nghttp2_bufs *bufs, const nghttp2_nv *nv,
1444
8.38k
                               size_t nvlen) {
1445
8.38k
  size_t i;
1446
8.38k
  int rv = 0;
1447
1448
8.38k
  if (deflater->ctx.bad) {
1449
0
    return NGHTTP2_ERR_HEADER_COMP;
1450
0
  }
1451
1452
8.38k
  if (deflater->notify_table_size_change) {
1453
168
    size_t min_hd_table_bufsize_max;
1454
1455
168
    min_hd_table_bufsize_max = deflater->min_hd_table_bufsize_max;
1456
1457
168
    deflater->notify_table_size_change = 0;
1458
168
    deflater->min_hd_table_bufsize_max = UINT32_MAX;
1459
1460
168
    if (deflater->ctx.hd_table_bufsize_max > min_hd_table_bufsize_max) {
1461
1462
28
      rv = emit_table_size(bufs, min_hd_table_bufsize_max);
1463
1464
28
      if (rv != 0) {
1465
0
        goto fail;
1466
0
      }
1467
28
    }
1468
1469
168
    rv = emit_table_size(bufs, deflater->ctx.hd_table_bufsize_max);
1470
1471
168
    if (rv != 0) {
1472
0
      goto fail;
1473
0
    }
1474
168
  }
1475
1476
465k
  for (i = 0; i < nvlen; ++i) {
1477
456k
    rv = deflate_nv(deflater, bufs, &nv[i]);
1478
456k
    if (rv != 0) {
1479
0
      goto fail;
1480
0
    }
1481
456k
  }
1482
1483
8.38k
  DEBUGF("deflatehd: all input name/value pairs were deflated\n");
1484
1485
8.38k
  return 0;
1486
0
fail:
1487
0
  DEBUGF("deflatehd: error return %d\n", rv);
1488
1489
0
  deflater->ctx.bad = 1;
1490
0
  return rv;
1491
8.38k
}
1492
1493
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
1494
                              size_t buflen, const nghttp2_nv *nv,
1495
0
                              size_t nvlen) {
1496
0
  return (ssize_t)nghttp2_hd_deflate_hd2(deflater, buf, buflen, nv, nvlen);
1497
0
}
1498
1499
nghttp2_ssize nghttp2_hd_deflate_hd2(nghttp2_hd_deflater *deflater,
1500
                                     uint8_t *buf, size_t buflen,
1501
0
                                     const nghttp2_nv *nv, size_t nvlen) {
1502
0
  nghttp2_bufs bufs;
1503
0
  int rv;
1504
0
  nghttp2_mem *mem;
1505
1506
0
  mem = deflater->ctx.mem;
1507
1508
0
  rv = nghttp2_bufs_wrap_init(&bufs, buf, buflen, mem);
1509
1510
0
  if (rv != 0) {
1511
0
    return rv;
1512
0
  }
1513
1514
0
  rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
1515
1516
0
  buflen = nghttp2_bufs_len(&bufs);
1517
1518
0
  nghttp2_bufs_wrap_free(&bufs);
1519
1520
0
  if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
1521
0
    return NGHTTP2_ERR_INSUFF_BUFSIZE;
1522
0
  }
1523
1524
0
  if (rv != 0) {
1525
0
    return rv;
1526
0
  }
1527
1528
0
  return (nghttp2_ssize)buflen;
1529
0
}
1530
1531
ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
1532
                                  const nghttp2_vec *vec, size_t veclen,
1533
0
                                  const nghttp2_nv *nv, size_t nvlen) {
1534
0
  return (ssize_t)nghttp2_hd_deflate_hd_vec2(deflater, vec, veclen, nv, nvlen);
1535
0
}
1536
1537
nghttp2_ssize nghttp2_hd_deflate_hd_vec2(nghttp2_hd_deflater *deflater,
1538
                                         const nghttp2_vec *vec, size_t veclen,
1539
0
                                         const nghttp2_nv *nv, size_t nvlen) {
1540
0
  nghttp2_bufs bufs;
1541
0
  int rv;
1542
0
  nghttp2_mem *mem;
1543
0
  size_t buflen;
1544
1545
0
  mem = deflater->ctx.mem;
1546
1547
0
  rv = nghttp2_bufs_wrap_init2(&bufs, vec, veclen, mem);
1548
1549
0
  if (rv != 0) {
1550
0
    return rv;
1551
0
  }
1552
1553
0
  rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
1554
1555
0
  buflen = nghttp2_bufs_len(&bufs);
1556
1557
0
  nghttp2_bufs_wrap_free(&bufs);
1558
1559
0
  if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
1560
0
    return NGHTTP2_ERR_INSUFF_BUFSIZE;
1561
0
  }
1562
1563
0
  if (rv != 0) {
1564
0
    return rv;
1565
0
  }
1566
1567
0
  return (nghttp2_ssize)buflen;
1568
0
}
1569
1570
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
1571
8.42k
                                const nghttp2_nv *nva, size_t nvlen) {
1572
8.42k
  size_t n = 0;
1573
8.42k
  size_t i;
1574
8.42k
  (void)deflater;
1575
1576
  /* Possible Maximum Header Table Size Change.  Encoding (1u << 31) -
1577
     1 using 4 bit prefix requires 6 bytes.  We may emit this at most
1578
     twice. */
1579
8.42k
  n += 12;
1580
1581
  /* Use Literal Header Field without indexing - New Name, since it is
1582
     most space consuming format.  Also we choose the less one between
1583
     non-huffman and huffman, so using literal byte count is
1584
     sufficient for upper bound.
1585
1586
     Encoding (1u << 31) - 1 using 7 bit prefix requires 6 bytes.  We
1587
     need 2 of this for |nvlen| header fields. */
1588
8.42k
  n += 6 * 2 * nvlen;
1589
1590
465k
  for (i = 0; i < nvlen; ++i) {
1591
457k
    n += nva[i].namelen + nva[i].valuelen;
1592
457k
  }
1593
1594
8.42k
  return n;
1595
8.42k
}
1596
1597
int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
1598
0
                           size_t deflate_hd_table_bufsize_max) {
1599
0
  return nghttp2_hd_deflate_new2(deflater_ptr, deflate_hd_table_bufsize_max,
1600
0
                                 NULL);
1601
0
}
1602
1603
int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr,
1604
                            size_t deflate_hd_table_bufsize_max,
1605
0
                            nghttp2_mem *mem) {
1606
0
  int rv;
1607
0
  nghttp2_hd_deflater *deflater;
1608
1609
0
  if (mem == NULL) {
1610
0
    mem = nghttp2_mem_default();
1611
0
  }
1612
1613
0
  deflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_deflater));
1614
1615
0
  if (deflater == NULL) {
1616
0
    return NGHTTP2_ERR_NOMEM;
1617
0
  }
1618
1619
0
  rv = nghttp2_hd_deflate_init2(deflater, deflate_hd_table_bufsize_max, mem);
1620
1621
0
  if (rv != 0) {
1622
0
    nghttp2_mem_free(mem, deflater);
1623
1624
0
    return rv;
1625
0
  }
1626
1627
0
  *deflater_ptr = deflater;
1628
1629
0
  return 0;
1630
0
}
1631
1632
0
void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater) {
1633
0
  nghttp2_mem *mem;
1634
1635
0
  mem = deflater->ctx.mem;
1636
1637
0
  nghttp2_hd_deflate_free(deflater);
1638
1639
0
  nghttp2_mem_free(mem, deflater);
1640
0
}
1641
1642
static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
1643
28.5k
                                           const uint8_t *in) {
1644
28.5k
  inflater->huffman_encoded = (*in & (1 << 7)) != 0;
1645
28.5k
}
1646
1647
/*
1648
 * Decodes the integer from the range [in, last).  The result is
1649
 * assigned to |inflater->left|.  If the |inflater->left| is 0, then
1650
 * it performs variable integer decoding from scratch. Otherwise, it
1651
 * uses the |inflater->left| as the initial value and continues to
1652
 * decode assuming that [in, last) begins with intermediary sequence.
1653
 *
1654
 * This function returns the number of bytes read if it succeeds, or
1655
 * one of the following negative error codes:
1656
 *
1657
 * NGHTTP2_ERR_HEADER_COMP
1658
 *   Integer decoding failed
1659
 */
1660
static nghttp2_ssize hd_inflate_read_len(nghttp2_hd_inflater *inflater,
1661
                                         int *rfin, const uint8_t *in,
1662
                                         const uint8_t *last, size_t prefix,
1663
225k
                                         size_t maxlen) {
1664
225k
  nghttp2_ssize rv;
1665
225k
  uint32_t out;
1666
1667
225k
  *rfin = 0;
1668
1669
225k
  rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
1670
225k
                     inflater->shift, in, last, prefix);
1671
1672
225k
  if (rv == -1) {
1673
80
    DEBUGF("inflatehd: integer decoding failed\n");
1674
80
    return NGHTTP2_ERR_HEADER_COMP;
1675
80
  }
1676
1677
225k
  if (out > maxlen) {
1678
534
    DEBUGF("inflatehd: integer exceeded the maximum value %zu\n", maxlen);
1679
534
    return NGHTTP2_ERR_HEADER_COMP;
1680
534
  }
1681
1682
225k
  inflater->left = out;
1683
1684
225k
  DEBUGF("inflatehd: decoded integer is %u\n", out);
1685
1686
225k
  return rv;
1687
225k
}
1688
1689
/*
1690
 * Reads |inflater->left| bytes from the range [in, last) and performs
1691
 * huffman decoding against them and pushes the result into the
1692
 * |buffer|.
1693
 *
1694
 * This function returns the number of bytes read if it succeeds, or
1695
 * one of the following negative error codes:
1696
 *
1697
 * NGHTTP2_ERR_NOMEM
1698
 *   Out of memory
1699
 * NGHTTP2_ERR_HEADER_COMP
1700
 *   Huffman decoding failed
1701
 */
1702
static nghttp2_ssize hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
1703
                                          nghttp2_buf *buf, const uint8_t *in,
1704
3.93k
                                          const uint8_t *last) {
1705
3.93k
  nghttp2_ssize readlen;
1706
3.93k
  int fin = 0;
1707
3.93k
  if ((size_t)(last - in) >= inflater->left) {
1708
3.47k
    last = in + inflater->left;
1709
3.47k
    fin = 1;
1710
3.47k
  }
1711
3.93k
  readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
1712
3.93k
                                   (size_t)(last - in), fin);
1713
1714
3.93k
  if (readlen < 0) {
1715
104
    DEBUGF("inflatehd: huffman decoding failed\n");
1716
104
    return readlen;
1717
104
  }
1718
3.83k
  if (nghttp2_hd_huff_decode_failure_state(&inflater->huff_decode_ctx)) {
1719
20
    DEBUGF("inflatehd: huffman decoding failed\n");
1720
20
    return NGHTTP2_ERR_HEADER_COMP;
1721
20
  }
1722
1723
3.81k
  inflater->left -= (size_t)readlen;
1724
3.81k
  return readlen;
1725
3.83k
}
1726
1727
/*
1728
 * Reads |inflater->left| bytes from the range [in, last) and copies
1729
 * them into the |buffer|.
1730
 *
1731
 * This function returns the number of bytes read if it succeeds, or
1732
 * one of the following negative error codes:
1733
 *
1734
 * NGHTTP2_ERR_NOMEM
1735
 *   Out of memory
1736
 * NGHTTP2_ERR_HEADER_COMP
1737
 *   Header decompression failed
1738
 */
1739
static nghttp2_ssize hd_inflate_read(nghttp2_hd_inflater *inflater,
1740
                                     nghttp2_buf *buf, const uint8_t *in,
1741
24.5k
                                     const uint8_t *last) {
1742
24.5k
  size_t len = nghttp2_min_size((size_t)(last - in), inflater->left);
1743
1744
24.5k
  buf->last = nghttp2_cpymem(buf->last, in, len);
1745
1746
24.5k
  inflater->left -= len;
1747
24.5k
  return (nghttp2_ssize)len;
1748
24.5k
}
1749
1750
/*
1751
 * Finalize indexed header representation reception.  The referenced
1752
 * header is always emitted, and |*nv_out| is filled with that value.
1753
 */
1754
static void hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
1755
184k
                                      nghttp2_hd_nv *nv_out) {
1756
184k
  nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1757
1758
184k
  emit_header(nv_out, &nv);
1759
184k
}
1760
1761
/*
1762
 * Finalize literal header representation - new name- reception. If
1763
 * header is emitted, |*nv_out| is filled with that value and 0 is
1764
 * returned.
1765
 *
1766
 * This function returns 0 if it succeeds, or one of the following
1767
 * negative error codes:
1768
 *
1769
 * NGHTTP2_ERR_NOMEM
1770
 *   Out of memory
1771
 */
1772
static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
1773
8.84k
                                     nghttp2_hd_nv *nv_out) {
1774
8.84k
  nghttp2_hd_nv nv;
1775
8.84k
  int rv;
1776
1777
8.84k
  if (inflater->no_index) {
1778
318
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1779
8.52k
  } else {
1780
8.52k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1781
8.52k
  }
1782
1783
8.84k
  nv.name = inflater->namercbuf;
1784
8.84k
  nv.value = inflater->valuercbuf;
1785
8.84k
  nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
1786
1787
8.84k
  if (inflater->index_required) {
1788
454
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1789
1790
454
    if (rv != 0) {
1791
0
      return rv;
1792
0
    }
1793
454
  }
1794
1795
8.84k
  emit_header(nv_out, &nv);
1796
1797
8.84k
  inflater->nv_name_keep = nv.name;
1798
8.84k
  inflater->nv_value_keep = nv.value;
1799
1800
8.84k
  inflater->namercbuf = NULL;
1801
8.84k
  inflater->valuercbuf = NULL;
1802
1803
8.84k
  return 0;
1804
8.84k
}
1805
1806
/*
1807
 * Finalize literal header representation - indexed name-
1808
 * reception. If header is emitted, |*nv_out| is filled with that
1809
 * value and 0 is returned.
1810
 *
1811
 * This function returns 0 if it succeeds, or one of the following
1812
 * negative error codes:
1813
 *
1814
 * NGHTTP2_ERR_NOMEM
1815
 *   Out of memory
1816
 */
1817
static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
1818
9.50k
                                     nghttp2_hd_nv *nv_out) {
1819
9.50k
  nghttp2_hd_nv nv;
1820
9.50k
  int rv;
1821
1822
9.50k
  nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1823
1824
9.50k
  if (inflater->no_index) {
1825
680
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1826
8.82k
  } else {
1827
8.82k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1828
8.82k
  }
1829
1830
9.50k
  nghttp2_rcbuf_incref(nv.name);
1831
1832
9.50k
  nv.value = inflater->valuercbuf;
1833
1834
9.50k
  if (inflater->index_required) {
1835
6.57k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1836
6.57k
    if (rv != 0) {
1837
0
      nghttp2_rcbuf_decref(nv.name);
1838
0
      return NGHTTP2_ERR_NOMEM;
1839
0
    }
1840
6.57k
  }
1841
1842
9.50k
  emit_header(nv_out, &nv);
1843
1844
9.50k
  inflater->nv_name_keep = nv.name;
1845
9.50k
  inflater->nv_value_keep = nv.value;
1846
1847
9.50k
  inflater->valuercbuf = NULL;
1848
1849
9.50k
  return 0;
1850
9.50k
}
1851
1852
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
1853
                              int *inflate_flags, uint8_t *in, size_t inlen,
1854
0
                              int in_final) {
1855
0
  return nghttp2_hd_inflate_hd2(inflater, nv_out, inflate_flags, in, inlen,
1856
0
                                in_final);
1857
0
}
1858
1859
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
1860
                               nghttp2_nv *nv_out, int *inflate_flags,
1861
0
                               const uint8_t *in, size_t inlen, int in_final) {
1862
0
  return (nghttp2_ssize)nghttp2_hd_inflate_hd3(inflater, nv_out, inflate_flags,
1863
0
                                               in, inlen, in_final);
1864
0
}
1865
1866
nghttp2_ssize nghttp2_hd_inflate_hd3(nghttp2_hd_inflater *inflater,
1867
                                     nghttp2_nv *nv_out, int *inflate_flags,
1868
                                     const uint8_t *in, size_t inlen,
1869
0
                                     int in_final) {
1870
0
  nghttp2_ssize rv;
1871
0
  nghttp2_hd_nv hd_nv;
1872
1873
0
  rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
1874
0
                                in_final);
1875
1876
0
  if (rv < 0) {
1877
0
    return rv;
1878
0
  }
1879
1880
0
  if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
1881
0
    nv_out->name = hd_nv.name->base;
1882
0
    nv_out->namelen = hd_nv.name->len;
1883
1884
0
    nv_out->value = hd_nv.value->base;
1885
0
    nv_out->valuelen = hd_nv.value->len;
1886
1887
0
    nv_out->flags = hd_nv.flags;
1888
0
  }
1889
1890
0
  return rv;
1891
0
}
1892
1893
nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
1894
                                       nghttp2_hd_nv *nv_out,
1895
                                       int *inflate_flags, const uint8_t *in,
1896
207k
                                       size_t inlen, int in_final) {
1897
207k
  nghttp2_ssize rv = 0;
1898
207k
  const uint8_t *first = in;
1899
207k
  const uint8_t *last = in + inlen;
1900
207k
  int rfin = 0;
1901
207k
  int busy = 0;
1902
207k
  nghttp2_mem *mem;
1903
1904
207k
  mem = inflater->ctx.mem;
1905
1906
207k
  if (inflater->ctx.bad) {
1907
0
    return NGHTTP2_ERR_HEADER_COMP;
1908
0
  }
1909
1910
207k
  DEBUGF("inflatehd: start state=%d\n", inflater->state);
1911
207k
  hd_inflate_keep_free(inflater);
1912
207k
  *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
1913
463k
  for (; in != last || busy;) {
1914
461k
    busy = 0;
1915
461k
    switch (inflater->state) {
1916
0
    case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1917
0
      if ((*in & 0xe0u) != 0x20u) {
1918
0
        DEBUGF("inflatehd: header table size change was expected, but saw "
1919
0
               "0x%02x as first byte",
1920
0
               *in);
1921
0
        rv = NGHTTP2_ERR_HEADER_COMP;
1922
0
        goto fail;
1923
0
      }
1924
    /* fall through */
1925
5.54k
    case NGHTTP2_HD_STATE_INFLATE_START:
1926
206k
    case NGHTTP2_HD_STATE_OPCODE:
1927
206k
      if ((*in & 0xe0u) == 0x20u) {
1928
2.12k
        DEBUGF("inflatehd: header table size change\n");
1929
2.12k
        if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
1930
501
          DEBUGF("inflatehd: header table size change must appear at the head "
1931
501
                 "of header block\n");
1932
501
          rv = NGHTTP2_ERR_HEADER_COMP;
1933
501
          goto fail;
1934
501
        }
1935
1.62k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1936
1.62k
        inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
1937
204k
      } else if (*in & 0x80u) {
1938
185k
        DEBUGF("inflatehd: indexed repr\n");
1939
185k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1940
185k
        inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1941
185k
      } else {
1942
19.6k
        if (*in == 0x40u || *in == 0 || *in == 0x10u) {
1943
9.38k
          DEBUGF("inflatehd: literal header repr - new name\n");
1944
9.38k
          inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
1945
9.38k
          inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
1946
10.2k
        } else {
1947
10.2k
          DEBUGF("inflatehd: literal header repr - indexed name\n");
1948
10.2k
          inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
1949
10.2k
          inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1950
10.2k
        }
1951
19.6k
        inflater->index_required = (*in & 0x40) != 0;
1952
19.6k
        inflater->no_index = (*in & 0xf0u) == 0x10u;
1953
19.6k
        DEBUGF("inflatehd: indexing required=%d, no_index=%d\n",
1954
19.6k
               inflater->index_required, inflater->no_index);
1955
19.6k
        if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1956
9.38k
          ++in;
1957
9.38k
        }
1958
19.6k
      }
1959
206k
      inflater->left = 0;
1960
206k
      inflater->shift = 0;
1961
206k
      break;
1962
1.67k
    case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
1963
1.67k
      rfin = 0;
1964
1.67k
      rv = hd_inflate_read_len(
1965
1.67k
          inflater, &rfin, in, last, 5,
1966
1.67k
          nghttp2_min_size(inflater->min_hd_table_bufsize_max,
1967
1.67k
                           inflater->settings_hd_table_bufsize_max));
1968
1.67k
      if (rv < 0) {
1969
43
        goto fail;
1970
43
      }
1971
1.62k
      in += rv;
1972
1.62k
      if (!rfin) {
1973
57
        goto almost_ok;
1974
57
      }
1975
1.57k
      DEBUGF("inflatehd: table_size=%zu\n", inflater->left);
1976
1.57k
      inflater->min_hd_table_bufsize_max = UINT32_MAX;
1977
1.57k
      inflater->ctx.hd_table_bufsize_max = inflater->left;
1978
1.57k
      hd_context_shrink_table_size(&inflater->ctx, NULL);
1979
1.57k
      inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
1980
1.57k
      break;
1981
195k
    case NGHTTP2_HD_STATE_READ_INDEX: {
1982
195k
      size_t prefixlen;
1983
1984
195k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
1985
185k
        prefixlen = 7;
1986
185k
      } else if (inflater->index_required) {
1987
7.08k
        prefixlen = 6;
1988
7.08k
      } else {
1989
3.21k
        prefixlen = 4;
1990
3.21k
      }
1991
1992
195k
      rfin = 0;
1993
195k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
1994
195k
                               get_max_index(&inflater->ctx));
1995
195k
      if (rv < 0) {
1996
456
        goto fail;
1997
456
      }
1998
1999
194k
      in += rv;
2000
2001
194k
      if (!rfin) {
2002
48
        goto almost_ok;
2003
48
      }
2004
2005
194k
      if (inflater->left == 0) {
2006
19
        rv = NGHTTP2_ERR_HEADER_COMP;
2007
19
        goto fail;
2008
19
      }
2009
2010
194k
      DEBUGF("inflatehd: index=%zu\n", inflater->left);
2011
194k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2012
184k
        inflater->index = inflater->left;
2013
184k
        --inflater->index;
2014
2015
184k
        hd_inflate_commit_indexed(inflater, nv_out);
2016
2017
184k
        inflater->state = NGHTTP2_HD_STATE_OPCODE;
2018
184k
        *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2019
184k
        return (nghttp2_ssize)(in - first);
2020
184k
      } else {
2021
10.2k
        inflater->index = inflater->left;
2022
10.2k
        --inflater->index;
2023
2024
10.2k
        inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2025
10.2k
      }
2026
10.2k
      break;
2027
194k
    }
2028
10.2k
    case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
2029
9.34k
      hd_inflate_set_huffman_encoded(inflater, in);
2030
9.34k
      inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
2031
9.34k
      inflater->left = 0;
2032
9.34k
      inflater->shift = 0;
2033
9.34k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2034
    /* Fall through */
2035
9.37k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
2036
9.37k
      rfin = 0;
2037
9.37k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2038
9.37k
      if (rv < 0) {
2039
53
        goto fail;
2040
53
      }
2041
9.31k
      in += rv;
2042
9.31k
      if (!rfin) {
2043
52
        DEBUGF("inflatehd: integer not fully decoded. current=%zu\n",
2044
52
               inflater->left);
2045
2046
52
        goto almost_ok;
2047
52
      }
2048
2049
9.26k
      if (inflater->huffman_encoded) {
2050
709
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2051
2052
709
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
2053
2054
709
        rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1,
2055
709
                               mem);
2056
8.55k
      } else {
2057
8.55k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
2058
8.55k
        rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
2059
8.55k
      }
2060
2061
9.26k
      if (rv != 0) {
2062
0
        goto fail;
2063
0
      }
2064
2065
9.26k
      nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
2066
9.26k
                            inflater->namercbuf->len);
2067
2068
9.26k
      break;
2069
734
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
2070
734
      rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
2071
734
      if (rv < 0) {
2072
24
        goto fail;
2073
24
      }
2074
2075
710
      in += rv;
2076
2077
710
      DEBUGF("inflatehd: %td bytes read\n", rv);
2078
2079
710
      if (inflater->left) {
2080
106
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2081
2082
106
        goto almost_ok;
2083
106
      }
2084
2085
604
      *inflater->namebuf.last = '\0';
2086
604
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2087
2088
604
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2089
2090
604
      break;
2091
8.56k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
2092
8.56k
      rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
2093
8.56k
      if (rv < 0) {
2094
0
        goto fail;
2095
0
      }
2096
2097
8.56k
      in += rv;
2098
2099
8.56k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2100
8.56k
      if (inflater->left) {
2101
128
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2102
2103
128
        goto almost_ok;
2104
128
      }
2105
2106
8.43k
      *inflater->namebuf.last = '\0';
2107
8.43k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2108
2109
8.43k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2110
2111
8.43k
      break;
2112
19.2k
    case NGHTTP2_HD_STATE_CHECK_VALUELEN:
2113
19.2k
      hd_inflate_set_huffman_encoded(inflater, in);
2114
19.2k
      inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
2115
19.2k
      inflater->left = 0;
2116
19.2k
      inflater->shift = 0;
2117
19.2k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2118
    /* Fall through */
2119
19.2k
    case NGHTTP2_HD_STATE_READ_VALUELEN:
2120
19.2k
      rfin = 0;
2121
19.2k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2122
19.2k
      if (rv < 0) {
2123
62
        goto fail;
2124
62
      }
2125
2126
19.1k
      in += rv;
2127
2128
19.1k
      if (!rfin) {
2129
48
        goto almost_ok;
2130
48
      }
2131
2132
19.1k
      DEBUGF("inflatehd: valuelen=%zu\n", inflater->left);
2133
2134
19.1k
      if (inflater->huffman_encoded) {
2135
3.15k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2136
2137
3.15k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
2138
2139
3.15k
        rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1,
2140
3.15k
                               mem);
2141
15.9k
      } else {
2142
15.9k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
2143
2144
15.9k
        rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
2145
15.9k
      }
2146
2147
19.1k
      if (rv != 0) {
2148
0
        goto fail;
2149
0
      }
2150
2151
19.1k
      nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
2152
19.1k
                            inflater->valuercbuf->len);
2153
2154
19.1k
      busy = 1;
2155
2156
19.1k
      break;
2157
3.20k
    case NGHTTP2_HD_STATE_READ_VALUEHUFF:
2158
3.20k
      rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
2159
3.20k
      if (rv < 0) {
2160
100
        goto fail;
2161
100
      }
2162
2163
3.10k
      in += rv;
2164
2165
3.10k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2166
2167
3.10k
      if (inflater->left) {
2168
335
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2169
2170
335
        goto almost_ok;
2171
335
      }
2172
2173
2.76k
      *inflater->valuebuf.last = '\0';
2174
2.76k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2175
2176
2.76k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2177
604
        rv = hd_inflate_commit_newname(inflater, nv_out);
2178
2.16k
      } else {
2179
2.16k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2180
2.16k
      }
2181
2182
2.76k
      if (rv != 0) {
2183
0
        goto fail;
2184
0
      }
2185
2186
2.76k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2187
2.76k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2188
2189
2.76k
      return (nghttp2_ssize)(in - first);
2190
16.0k
    case NGHTTP2_HD_STATE_READ_VALUE:
2191
16.0k
      rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
2192
16.0k
      if (rv < 0) {
2193
0
        DEBUGF("inflatehd: value read failure %td: %s\n", rv,
2194
0
               nghttp2_strerror((int)rv));
2195
0
        goto fail;
2196
0
      }
2197
2198
16.0k
      in += rv;
2199
2200
16.0k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2201
2202
16.0k
      if (inflater->left) {
2203
445
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2204
445
        goto almost_ok;
2205
445
      }
2206
2207
15.5k
      *inflater->valuebuf.last = '\0';
2208
15.5k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2209
2210
15.5k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2211
8.23k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2212
8.23k
      } else {
2213
7.34k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2214
7.34k
      }
2215
2216
15.5k
      if (rv != 0) {
2217
0
        goto fail;
2218
0
      }
2219
2220
15.5k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2221
15.5k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2222
2223
15.5k
      return (nghttp2_ssize)(in - first);
2224
461k
    }
2225
461k
  }
2226
2227
2.06k
  assert(in == last);
2228
2229
2.06k
  DEBUGF("inflatehd: all input bytes were processed\n");
2230
2231
2.06k
  if (in_final) {
2232
1.34k
    DEBUGF("inflatehd: in_final set\n");
2233
2234
1.34k
    if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
2235
1.34k
        inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
2236
6
      DEBUGF("inflatehd: unacceptable state=%d\n", inflater->state);
2237
6
      rv = NGHTTP2_ERR_HEADER_COMP;
2238
2239
6
      goto fail;
2240
6
    }
2241
1.33k
    *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
2242
1.33k
  }
2243
2.06k
  return (nghttp2_ssize)(in - first);
2244
2245
1.21k
almost_ok:
2246
1.21k
  if (in_final) {
2247
48
    DEBUGF("inflatehd: input ended prematurely\n");
2248
2249
48
    rv = NGHTTP2_ERR_HEADER_COMP;
2250
2251
48
    goto fail;
2252
48
  }
2253
1.17k
  return (nghttp2_ssize)(in - first);
2254
2255
1.31k
fail:
2256
1.31k
  DEBUGF("inflatehd: error return %td\n", rv);
2257
2258
1.31k
  inflater->ctx.bad = 1;
2259
1.31k
  return rv;
2260
1.21k
}
2261
2262
1.33k
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
2263
1.33k
  hd_inflate_keep_free(inflater);
2264
1.33k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2265
1.33k
  return 0;
2266
1.33k
}
2267
2268
0
int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr) {
2269
0
  return nghttp2_hd_inflate_new2(inflater_ptr, NULL);
2270
0
}
2271
2272
int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr,
2273
0
                            nghttp2_mem *mem) {
2274
0
  int rv;
2275
0
  nghttp2_hd_inflater *inflater;
2276
2277
0
  if (mem == NULL) {
2278
0
    mem = nghttp2_mem_default();
2279
0
  }
2280
2281
0
  inflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_inflater));
2282
2283
0
  if (inflater == NULL) {
2284
0
    return NGHTTP2_ERR_NOMEM;
2285
0
  }
2286
2287
0
  rv = nghttp2_hd_inflate_init(inflater, mem);
2288
2289
0
  if (rv != 0) {
2290
0
    nghttp2_mem_free(mem, inflater);
2291
2292
0
    return rv;
2293
0
  }
2294
2295
0
  *inflater_ptr = inflater;
2296
2297
0
  return 0;
2298
0
}
2299
2300
0
void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater) {
2301
0
  nghttp2_mem *mem;
2302
2303
0
  mem = inflater->ctx.mem;
2304
0
  nghttp2_hd_inflate_free(inflater);
2305
2306
0
  nghttp2_mem_free(mem, inflater);
2307
0
}
2308
2309
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t idx,
2310
0
                                  nghttp2_nv *nv, int indexing_mode) {
2311
2312
0
  return emit_indname_block(bufs, idx, nv, indexing_mode);
2313
0
}
2314
2315
int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
2316
0
                                  int indexing_mode) {
2317
0
  return emit_newname_block(bufs, nv, indexing_mode);
2318
0
}
2319
2320
0
int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
2321
0
  return emit_table_size(bufs, table_size);
2322
0
}
2323
2324
nghttp2_ssize nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr,
2325
                                       int *fin, uint32_t initial, size_t shift,
2326
                                       uint8_t *in, uint8_t *last,
2327
0
                                       size_t prefix) {
2328
0
  return decode_length(res, shift_ptr, fin, initial, shift, in, last, prefix);
2329
0
}
2330
2331
static const nghttp2_nv *hd_get_table_entry(nghttp2_hd_context *context,
2332
0
                                            size_t idx) {
2333
0
  if (idx == 0) {
2334
0
    return NULL;
2335
0
  }
2336
2337
0
  --idx;
2338
2339
0
  if (!INDEX_RANGE_VALID(context, idx)) {
2340
0
    return NULL;
2341
0
  }
2342
2343
0
  return nghttp2_hd_table_get2(context, idx);
2344
0
}
2345
2346
0
size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater) {
2347
0
  return get_max_index(&deflater->ctx);
2348
0
}
2349
2350
const nghttp2_nv *
2351
0
nghttp2_hd_deflate_get_table_entry(nghttp2_hd_deflater *deflater, size_t idx) {
2352
0
  return hd_get_table_entry(&deflater->ctx, idx);
2353
0
}
2354
2355
size_t
2356
0
nghttp2_hd_deflate_get_dynamic_table_size(nghttp2_hd_deflater *deflater) {
2357
0
  return deflater->ctx.hd_table_bufsize;
2358
0
}
2359
2360
size_t
2361
0
nghttp2_hd_deflate_get_max_dynamic_table_size(nghttp2_hd_deflater *deflater) {
2362
0
  return deflater->ctx.hd_table_bufsize_max;
2363
0
}
2364
2365
0
size_t nghttp2_hd_inflate_get_num_table_entries(nghttp2_hd_inflater *inflater) {
2366
0
  return get_max_index(&inflater->ctx);
2367
0
}
2368
2369
const nghttp2_nv *
2370
0
nghttp2_hd_inflate_get_table_entry(nghttp2_hd_inflater *inflater, size_t idx) {
2371
0
  return hd_get_table_entry(&inflater->ctx, idx);
2372
0
}
2373
2374
size_t
2375
0
nghttp2_hd_inflate_get_dynamic_table_size(nghttp2_hd_inflater *inflater) {
2376
0
  return inflater->ctx.hd_table_bufsize;
2377
0
}
2378
2379
size_t
2380
0
nghttp2_hd_inflate_get_max_dynamic_table_size(nghttp2_hd_inflater *inflater) {
2381
0
  return inflater->ctx.hd_table_bufsize_max;
2382
0
}