Coverage Report

Created: 2025-11-24 06:18

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