Coverage Report

Created: 2026-03-21 06:52

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