Coverage Report

Created: 2026-01-25 06:21

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
110k
static int memeq(const void *s1, const void *s2, size_t n) {
115
110k
  return memcmp(s1, s2, n) == 0;
116
110k
}
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.11k
  case 2:
125
2.11k
    switch (name[1]) {
126
1.51k
    case 'e':
127
1.51k
      if (memeq("t", name, 1)) {
128
868
        return NGHTTP2_TOKEN_TE;
129
868
      }
130
646
      break;
131
2.11k
    }
132
1.25k
    break;
133
3.52k
  case 3:
134
3.52k
    switch (name[2]) {
135
1.25k
    case 'a':
136
1.25k
      if (memeq("vi", name, 2)) {
137
509
        return NGHTTP2_TOKEN_VIA;
138
509
      }
139
743
      break;
140
1.19k
    case 'e':
141
1.19k
      if (memeq("ag", name, 2)) {
142
509
        return NGHTTP2_TOKEN_AGE;
143
509
      }
144
684
      break;
145
3.52k
    }
146
2.50k
    break;
147
8.18k
  case 4:
148
8.18k
    switch (name[3]) {
149
1.20k
    case 'e':
150
1.20k
      if (memeq("dat", name, 3)) {
151
582
        return NGHTTP2_TOKEN_DATE;
152
582
      }
153
621
      break;
154
1.02k
    case 'g':
155
1.02k
      if (memeq("eta", name, 3)) {
156
408
        return NGHTTP2_TOKEN_ETAG;
157
408
      }
158
618
      break;
159
1.20k
    case 'k':
160
1.20k
      if (memeq("lin", name, 3)) {
161
593
        return NGHTTP2_TOKEN_LINK;
162
593
      }
163
608
      break;
164
1.23k
    case 'm':
165
1.23k
      if (memeq("fro", name, 3)) {
166
627
        return NGHTTP2_TOKEN_FROM;
167
627
      }
168
607
      break;
169
962
    case 't':
170
962
      if (memeq("hos", name, 3)) {
171
409
        return NGHTTP2_TOKEN_HOST;
172
409
      }
173
553
      break;
174
1.12k
    case 'y':
175
1.12k
      if (memeq("var", name, 3)) {
176
452
        return NGHTTP2_TOKEN_VARY;
177
452
      }
178
676
      break;
179
8.18k
    }
180
5.11k
    break;
181
5.11k
  case 5:
182
3.03k
    switch (name[4]) {
183
876
    case 'e':
184
876
      if (memeq("rang", name, 4)) {
185
406
        return NGHTTP2_TOKEN_RANGE;
186
406
      }
187
470
      break;
188
824
    case 'h':
189
824
      if (memeq(":pat", name, 4)) {
190
347
        return NGHTTP2_TOKEN__PATH;
191
347
      }
192
477
      break;
193
687
    case 'w':
194
687
      if (memeq("allo", name, 4)) {
195
383
        return NGHTTP2_TOKEN_ALLOW;
196
383
      }
197
304
      break;
198
3.03k
    }
199
1.89k
    break;
200
3.15k
  case 6:
201
3.15k
    switch (name[5]) {
202
646
    case 'e':
203
646
      if (memeq("cooki", name, 5)) {
204
345
        return NGHTTP2_TOKEN_COOKIE;
205
345
      }
206
301
      break;
207
580
    case 'r':
208
580
      if (memeq("serve", name, 5)) {
209
279
        return NGHTTP2_TOKEN_SERVER;
210
279
      }
211
301
      break;
212
1.16k
    case 't':
213
1.16k
      if (memeq("accep", name, 5)) {
214
396
        return NGHTTP2_TOKEN_ACCEPT;
215
396
      }
216
769
      if (memeq("expec", name, 5)) {
217
318
        return NGHTTP2_TOKEN_EXPECT;
218
318
      }
219
451
      break;
220
3.15k
    }
221
1.81k
    break;
222
5.79k
  case 7:
223
5.79k
    switch (name[6]) {
224
622
    case 'd':
225
622
      if (memeq(":metho", name, 6)) {
226
280
        return NGHTTP2_TOKEN__METHOD;
227
280
      }
228
342
      break;
229
2.14k
    case 'e':
230
2.14k
      if (memeq(":schem", name, 6)) {
231
288
        return NGHTTP2_TOKEN__SCHEME;
232
288
      }
233
1.85k
      if (memeq("upgrad", name, 6)) {
234
1.45k
        return NGHTTP2_TOKEN_UPGRADE;
235
1.45k
      }
236
407
      break;
237
925
    case 'h':
238
925
      if (memeq("refres", name, 6)) {
239
620
        return NGHTTP2_TOKEN_REFRESH;
240
620
      }
241
305
      break;
242
609
    case 'r':
243
609
      if (memeq("refere", name, 6)) {
244
278
        return NGHTTP2_TOKEN_REFERER;
245
278
      }
246
331
      break;
247
905
    case 's':
248
905
      if (memeq(":statu", name, 6)) {
249
313
        return NGHTTP2_TOKEN__STATUS;
250
313
      }
251
592
      if (memeq("expire", name, 6)) {
252
278
        return NGHTTP2_TOKEN_EXPIRES;
253
278
      }
254
314
      break;
255
5.79k
    }
256
2.29k
    break;
257
12.1k
  case 8:
258
12.1k
    switch (name[7]) {
259
743
    case 'e':
260
743
      if (memeq("if-rang", name, 7)) {
261
333
        return NGHTTP2_TOKEN_IF_RANGE;
262
333
      }
263
410
      break;
264
583
    case 'h':
265
583
      if (memeq("if-matc", name, 7)) {
266
279
        return NGHTTP2_TOKEN_IF_MATCH;
267
279
      }
268
304
      break;
269
585
    case 'n':
270
585
      if (memeq("locatio", name, 7)) {
271
279
        return NGHTTP2_TOKEN_LOCATION;
272
279
      }
273
306
      break;
274
9.29k
    case 'y':
275
9.29k
      if (memeq("priorit", name, 7)) {
276
8.98k
        return NGHTTP2_TOKEN_PRIORITY;
277
8.98k
      }
278
312
      break;
279
12.1k
    }
280
2.32k
    break;
281
2.32k
  case 9:
282
1.61k
    switch (name[8]) {
283
1.12k
    case 'l':
284
1.12k
      if (memeq(":protoco", name, 8)) {
285
731
        return NGHTTP2_TOKEN__PROTOCOL;
286
731
      }
287
397
      break;
288
1.61k
    }
289
885
    break;
290
5.10k
  case 10:
291
5.10k
    switch (name[9]) {
292
1.26k
    case 'e':
293
1.26k
      if (memeq("keep-aliv", name, 9)) {
294
395
        return NGHTTP2_TOKEN_KEEP_ALIVE;
295
395
      }
296
866
      if (memeq("set-cooki", name, 9)) {
297
279
        return NGHTTP2_TOKEN_SET_COOKIE;
298
279
      }
299
587
      break;
300
957
    case 'n':
301
957
      if (memeq("connectio", name, 9)) {
302
280
        return NGHTTP2_TOKEN_CONNECTION;
303
280
      }
304
677
      break;
305
1.48k
    case 't':
306
1.48k
      if (memeq("user-agen", name, 9)) {
307
1.01k
        return NGHTTP2_TOKEN_USER_AGENT;
308
1.01k
      }
309
473
      break;
310
789
    case 'y':
311
789
      if (memeq(":authorit", name, 9)) {
312
311
        return NGHTTP2_TOKEN__AUTHORITY;
313
311
      }
314
478
      break;
315
5.10k
    }
316
2.83k
    break;
317
2.83k
  case 11:
318
1.08k
    switch (name[10]) {
319
730
    case 'r':
320
730
      if (memeq("retry-afte", name, 10)) {
321
348
        return NGHTTP2_TOKEN_RETRY_AFTER;
322
348
      }
323
382
      break;
324
1.08k
    }
325
738
    break;
326
1.67k
  case 12:
327
1.67k
    switch (name[11]) {
328
679
    case 'e':
329
679
      if (memeq("content-typ", name, 11)) {
330
294
        return NGHTTP2_TOKEN_CONTENT_TYPE;
331
294
      }
332
385
      break;
333
629
    case 's':
334
629
      if (memeq("max-forward", name, 11)) {
335
279
        return NGHTTP2_TOKEN_MAX_FORWARDS;
336
279
      }
337
350
      break;
338
1.67k
    }
339
1.10k
    break;
340
4.23k
  case 13:
341
4.23k
    switch (name[12]) {
342
640
    case 'd':
343
640
      if (memeq("last-modifie", name, 12)) {
344
280
        return NGHTTP2_TOKEN_LAST_MODIFIED;
345
280
      }
346
360
      break;
347
616
    case 'e':
348
616
      if (memeq("content-rang", name, 12)) {
349
287
        return NGHTTP2_TOKEN_CONTENT_RANGE;
350
287
      }
351
329
      break;
352
622
    case 'h':
353
622
      if (memeq("if-none-matc", name, 12)) {
354
278
        return NGHTTP2_TOKEN_IF_NONE_MATCH;
355
278
      }
356
344
      break;
357
637
    case 'l':
358
637
      if (memeq("cache-contro", name, 12)) {
359
286
        return NGHTTP2_TOKEN_CACHE_CONTROL;
360
286
      }
361
351
      break;
362
621
    case 'n':
363
621
      if (memeq("authorizatio", name, 12)) {
364
278
        return NGHTTP2_TOKEN_AUTHORIZATION;
365
278
      }
366
343
      break;
367
650
    case 's':
368
650
      if (memeq("accept-range", name, 12)) {
369
279
        return NGHTTP2_TOKEN_ACCEPT_RANGES;
370
279
      }
371
371
      break;
372
4.23k
    }
373
2.54k
    break;
374
2.54k
  case 14:
375
1.97k
    switch (name[13]) {
376
862
    case 'h':
377
862
      if (memeq("content-lengt", name, 13)) {
378
278
        return NGHTTP2_TOKEN_CONTENT_LENGTH;
379
278
      }
380
584
      break;
381
757
    case 't':
382
757
      if (memeq("accept-charse", name, 13)) {
383
355
        return NGHTTP2_TOKEN_ACCEPT_CHARSET;
384
355
      }
385
402
      break;
386
1.97k
    }
387
1.34k
    break;
388
1.63k
  case 15:
389
1.63k
    switch (name[14]) {
390
662
    case 'e':
391
662
      if (memeq("accept-languag", name, 14)) {
392
280
        return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
393
280
      }
394
382
      break;
395
613
    case 'g':
396
613
      if (memeq("accept-encodin", name, 14)) {
397
279
        return NGHTTP2_TOKEN_ACCEPT_ENCODING;
398
279
      }
399
334
      break;
400
1.63k
    }
401
1.07k
    break;
402
4.08k
  case 16:
403
4.08k
    switch (name[15]) {
404
1.47k
    case 'e':
405
1.47k
      if (memeq("content-languag", name, 15)) {
406
350
        return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
407
350
      }
408
1.12k
      if (memeq("www-authenticat", name, 15)) {
409
465
        return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
410
465
      }
411
656
      break;
412
656
    case 'g':
413
649
      if (memeq("content-encodin", name, 15)) {
414
280
        return NGHTTP2_TOKEN_CONTENT_ENCODING;
415
280
      }
416
369
      break;
417
1.20k
    case 'n':
418
1.20k
      if (memeq("content-locatio", name, 15)) {
419
278
        return NGHTTP2_TOKEN_CONTENT_LOCATION;
420
278
      }
421
928
      if (memeq("proxy-connectio", name, 15)) {
422
401
        return NGHTTP2_TOKEN_PROXY_CONNECTION;
423
401
      }
424
527
      break;
425
4.08k
    }
426
2.31k
    break;
427
2.31k
  case 17:
428
1.97k
    switch (name[16]) {
429
661
    case 'e':
430
661
      if (memeq("if-modified-sinc", name, 16)) {
431
279
        return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
432
279
      }
433
382
      break;
434
751
    case 'g':
435
751
      if (memeq("transfer-encodin", name, 16)) {
436
356
        return NGHTTP2_TOKEN_TRANSFER_ENCODING;
437
356
      }
438
395
      break;
439
1.97k
    }
440
1.33k
    break;
441
1.51k
  case 18:
442
1.51k
    switch (name[17]) {
443
1.04k
    case 'e':
444
1.04k
      if (memeq("proxy-authenticat", name, 17)) {
445
285
        return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
446
285
      }
447
755
      break;
448
1.51k
    }
449
1.22k
    break;
450
3.05k
  case 19:
451
3.05k
    switch (name[18]) {
452
750
    case 'e':
453
750
      if (memeq("if-unmodified-sinc", name, 18)) {
454
278
        return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
455
278
      }
456
472
      break;
457
1.57k
    case 'n':
458
1.57k
      if (memeq("content-dispositio", name, 18)) {
459
370
        return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
460
370
      }
461
1.20k
      if (memeq("proxy-authorizatio", name, 18)) {
462
787
        return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
463
787
      }
464
415
      break;
465
3.05k
    }
466
1.61k
    break;
467
1.61k
  case 25:
468
997
    switch (name[24]) {
469
510
    case 'y':
470
510
      if (memeq("strict-transport-securit", name, 24)) {
471
151
        return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
472
151
      }
473
359
      break;
474
997
    }
475
846
    break;
476
1.02k
  case 27:
477
1.02k
    switch (name[26]) {
478
644
    case 'n':
479
644
      if (memeq("access-control-allow-origi", name, 26)) {
480
288
        return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
481
288
      }
482
356
      break;
483
1.02k
    }
484
740
    break;
485
128k
  }
486
96.6k
  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
24.1k
static int name_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
509
24.1k
  return a->name->len == b->namelen &&
510
24.0k
         memeq(a->name->base, b->name, b->namelen);
511
24.1k
}
512
513
24.4k
static int value_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
514
24.4k
  return a->value->len == b->valuelen &&
515
23.6k
         memeq(a->value->base, b->value, b->valuelen);
516
24.4k
}
517
518
31.2k
static uint32_t name_hash(const nghttp2_nv *nv) {
519
  /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
520
31.2k
  uint32_t h = 2166136261u;
521
31.2k
  size_t i;
522
523
84.6k
  for (i = 0; i < nv->namelen; ++i) {
524
53.3k
    h ^= nv->name[i];
525
53.3k
    h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
526
53.3k
  }
527
528
31.2k
  return h;
529
31.2k
}
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
8.79k
static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
536
8.79k
  nghttp2_hd_entry **bucket;
537
538
8.79k
  bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
539
540
8.79k
  if (*bucket == NULL) {
541
7.88k
    *bucket = ent;
542
7.88k
    return;
543
7.88k
  }
544
545
  /* lower index is linked near the root */
546
906
  ent->next = *bucket;
547
906
  *bucket = ent;
548
906
}
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
32.8k
                                     uint32_t hash, int name_only) {
553
32.8k
  nghttp2_hd_entry *p;
554
32.8k
  nghttp2_hd_entry *res = NULL;
555
556
32.8k
  *exact_match = 0;
557
558
34.8k
  for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) {
559
24.9k
    if (token != p->nv.token ||
560
24.8k
        (token == -1 && (hash != p->hash || !name_eq(&p->nv, nv)))) {
561
518
      continue;
562
518
    }
563
24.4k
    if (!res) {
564
23.6k
      res = p;
565
23.6k
      if (name_only) {
566
18
        break;
567
18
      }
568
23.6k
    }
569
24.4k
    if (value_eq(&p->nv, nv)) {
570
22.9k
      res = p;
571
22.9k
      *exact_match = 1;
572
22.9k
      break;
573
22.9k
    }
574
24.4k
  }
575
576
32.8k
  return res;
577
32.8k
}
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
450k
  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
126k
                                        size_t idx) {
623
126k
  assert(idx < ringbuf->len);
624
126k
  return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
625
126k
}
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
48.2k
    nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
659
660
48.2k
    nghttp2_hd_entry_free(ent);
661
48.2k
    nghttp2_mem_free(mem, ent);
662
48.2k
  }
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.62k
static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
683
6.62k
  assert(ringbuf->len > 0);
684
6.62k
  --ringbuf->len;
685
6.62k
}
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.68k
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
710
4.68k
  return nghttp2_hd_deflate_init2(
711
4.68k
    deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
712
4.68k
}
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
361k
static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
775
361k
  nghttp2_rcbuf_decref(inflater->nv_value_keep);
776
361k
  nghttp2_rcbuf_decref(inflater->nv_name_keep);
777
778
361k
  inflater->nv_value_keep = NULL;
779
361k
  inflater->nv_name_keep = NULL;
780
361k
}
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
94.9k
static size_t entry_room(size_t namelen, size_t valuelen) {
796
94.9k
  return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
797
94.9k
}
798
799
268k
static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
800
268k
  DEBUGF("inflatehd: header emission: %s: %s\n", nv->name->base,
801
268k
         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
268k
  *nv_out = *nv;
805
268k
}
806
807
41.7k
static size_t count_encoded_length(size_t n, size_t prefix) {
808
41.7k
  size_t k = (size_t)((1 << prefix) - 1);
809
41.7k
  size_t len = 0;
810
811
41.7k
  if (n < k) {
812
40.8k
    return 1;
813
40.8k
  }
814
815
825
  n -= k;
816
825
  ++len;
817
818
1.29k
  for (; n >= 128; n >>= 7, ++len)
819
474
    ;
820
821
825
  return len + 1;
822
41.7k
}
823
824
41.7k
static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
825
41.7k
  size_t k = (size_t)((1 << prefix) - 1);
826
41.7k
  uint8_t *begin = buf;
827
828
41.7k
  *buf = (uint8_t)(*buf & ~k);
829
830
41.7k
  if (n < k) {
831
40.8k
    *buf = (uint8_t)(*buf | n);
832
40.8k
    return 1;
833
40.8k
  }
834
835
825
  *buf = (uint8_t)(*buf | k);
836
825
  ++buf;
837
838
825
  n -= k;
839
840
1.29k
  for (; n >= 128; n >>= 7) {
841
474
    *buf++ = (uint8_t)((1 << 7) | (n & 0x7f));
842
474
  }
843
844
825
  *buf++ = (uint8_t)n;
845
846
825
  return (size_t)(buf - begin);
847
41.7k
}
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
412k
                                   size_t prefix) {
870
412k
  uint32_t k = (uint8_t)((1 << prefix) - 1);
871
412k
  uint32_t n = initial;
872
412k
  const uint8_t *start = in;
873
874
412k
  *shift_ptr = 0;
875
412k
  *fin = 0;
876
877
412k
  if (n == 0) {
878
411k
    if ((*in & k) != k) {
879
399k
      *res = (*in) & k;
880
399k
      *fin = 1;
881
399k
      return 1;
882
399k
    }
883
884
11.4k
    n = k;
885
886
11.4k
    if (++in == last) {
887
226
      *res = n;
888
226
      return (nghttp2_ssize)(in - start);
889
226
    }
890
11.4k
  }
891
892
33.9k
  for (; in != last; ++in, shift += 7) {
893
31.6k
    uint32_t add = *in & 0x7f;
894
895
31.6k
    if (shift >= 32) {
896
50
      DEBUGF("inflate: shift exponent overflow\n");
897
50
      return -1;
898
50
    }
899
900
31.5k
    if ((UINT32_MAX >> shift) < add) {
901
70
      DEBUGF("inflate: integer overflow on shift\n");
902
70
      return -1;
903
70
    }
904
905
31.4k
    add <<= shift;
906
907
31.4k
    if (UINT32_MAX - add < n) {
908
82
      DEBUGF("inflate: integer overflow on addition\n");
909
82
      return -1;
910
82
    }
911
912
31.4k
    n += add;
913
914
31.4k
    if ((*in & (1 << 7)) == 0) {
915
10.2k
      break;
916
10.2k
    }
917
31.4k
  }
918
919
12.5k
  *shift_ptr = shift;
920
921
12.5k
  if (in == last) {
922
2.36k
    *res = n;
923
2.36k
    return (nghttp2_ssize)(in - start);
924
2.36k
  }
925
926
10.2k
  *res = n;
927
10.2k
  *fin = 1;
928
10.2k
  return (nghttp2_ssize)(in + 1 - start);
929
12.5k
}
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
23.8k
static int emit_indexed_block(nghttp2_bufs *bufs, size_t idx) {
960
23.8k
  int rv;
961
23.8k
  size_t blocklen;
962
23.8k
  uint8_t sb[16];
963
23.8k
  uint8_t *bufp;
964
965
23.8k
  blocklen = count_encoded_length(idx + 1, 7);
966
967
23.8k
  DEBUGF("deflatehd: emit indexed index=%zu, %zu bytes\n", idx, blocklen);
968
969
23.8k
  if (sizeof(sb) < blocklen) {
970
0
    return NGHTTP2_ERR_HEADER_COMP;
971
0
  }
972
973
23.8k
  bufp = sb;
974
23.8k
  *bufp = 0x80u;
975
23.8k
  encode_length(bufp, idx + 1, 7);
976
977
23.8k
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
978
23.8k
  if (rv != 0) {
979
0
    return rv;
980
0
  }
981
982
23.8k
  return 0;
983
23.8k
}
984
985
16.9k
static int emit_string(nghttp2_bufs *bufs, const uint8_t *str, size_t len) {
986
16.9k
  int rv;
987
16.9k
  uint8_t sb[16];
988
16.9k
  uint8_t *bufp;
989
16.9k
  size_t blocklen;
990
16.9k
  size_t enclen;
991
16.9k
  int huffman = 0;
992
993
16.9k
  enclen = nghttp2_hd_huff_encode_count(str, len);
994
995
16.9k
  if (enclen < len) {
996
1.29k
    huffman = 1;
997
15.6k
  } else {
998
15.6k
    enclen = len;
999
15.6k
  }
1000
1001
16.9k
  blocklen = count_encoded_length(enclen, 7);
1002
1003
16.9k
  DEBUGF("deflatehd: emit string str=%.*s, length=%zu, huffman=%d, "
1004
16.9k
         "encoded_length=%zu\n",
1005
16.9k
         (int)len, (const char *)str, len, huffman, enclen);
1006
1007
16.9k
  if (sizeof(sb) < blocklen) {
1008
0
    return NGHTTP2_ERR_HEADER_COMP;
1009
0
  }
1010
1011
16.9k
  bufp = sb;
1012
16.9k
  *bufp = huffman ? 1 << 7 : 0;
1013
16.9k
  encode_length(bufp, enclen, 7);
1014
1015
16.9k
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1016
16.9k
  if (rv != 0) {
1017
0
    return rv;
1018
0
  }
1019
1020
16.9k
  if (huffman) {
1021
1.29k
    rv = nghttp2_hd_huff_encode(bufs, str, len);
1022
15.6k
  } else {
1023
15.6k
    assert(enclen == len);
1024
15.6k
    rv = nghttp2_bufs_add(bufs, str, len);
1025
15.6k
  }
1026
1027
16.9k
  return rv;
1028
16.9k
}
1029
1030
8.92k
static uint8_t pack_first_byte(int indexing_mode) {
1031
8.92k
  switch (indexing_mode) {
1032
8.79k
  case NGHTTP2_HD_WITH_INDEXING:
1033
8.79k
    return 0x40u;
1034
67
  case NGHTTP2_HD_WITHOUT_INDEXING:
1035
67
    return 0;
1036
62
  case NGHTTP2_HD_NEVER_INDEXING:
1037
62
    return 0x10u;
1038
0
  default:
1039
0
    assert(0);
1040
8.92k
  }
1041
  /* This is required to compile with android NDK r10d +
1042
     --enable-werror */
1043
0
  return 0;
1044
8.92k
}
1045
1046
static int emit_indname_block(nghttp2_bufs *bufs, size_t idx,
1047
911
                              const nghttp2_nv *nv, int indexing_mode) {
1048
911
  int rv;
1049
911
  uint8_t *bufp;
1050
911
  size_t blocklen;
1051
911
  uint8_t sb[16];
1052
911
  size_t prefixlen;
1053
1054
911
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1055
782
    prefixlen = 6;
1056
782
  } else {
1057
129
    prefixlen = 4;
1058
129
  }
1059
1060
911
  DEBUGF("deflatehd: emit indname index=%zu, valuelen=%zu, indexing_mode=%d\n",
1061
911
         idx, nv->valuelen, indexing_mode);
1062
1063
911
  blocklen = count_encoded_length(idx + 1, prefixlen);
1064
1065
911
  if (sizeof(sb) < blocklen) {
1066
0
    return NGHTTP2_ERR_HEADER_COMP;
1067
0
  }
1068
1069
911
  bufp = sb;
1070
1071
911
  *bufp = pack_first_byte(indexing_mode);
1072
1073
911
  encode_length(bufp, idx + 1, prefixlen);
1074
1075
911
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1076
911
  if (rv != 0) {
1077
0
    return rv;
1078
0
  }
1079
1080
911
  rv = emit_string(bufs, nv->value, nv->valuelen);
1081
911
  if (rv != 0) {
1082
0
    return rv;
1083
0
  }
1084
1085
911
  return 0;
1086
911
}
1087
1088
static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
1089
8.01k
                              int indexing_mode) {
1090
8.01k
  int rv;
1091
1092
8.01k
  DEBUGF(
1093
8.01k
    "deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
1094
8.01k
    nv->namelen, nv->valuelen, indexing_mode);
1095
1096
8.01k
  rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
1097
8.01k
  if (rv != 0) {
1098
0
    return rv;
1099
0
  }
1100
1101
8.01k
  rv = emit_string(bufs, nv->name, nv->namelen);
1102
8.01k
  if (rv != 0) {
1103
0
    return rv;
1104
0
  }
1105
1106
8.01k
  rv = emit_string(bufs, nv->value, nv->valuelen);
1107
8.01k
  if (rv != 0) {
1108
0
    return rv;
1109
0
  }
1110
1111
8.01k
  return 0;
1112
8.01k
}
1113
1114
static int add_hd_table_incremental(nghttp2_hd_context *context,
1115
                                    nghttp2_hd_nv *nv, nghttp2_hd_map *map,
1116
55.8k
                                    uint32_t hash) {
1117
55.8k
  int rv;
1118
55.8k
  nghttp2_hd_entry *new_ent;
1119
55.8k
  size_t room;
1120
55.8k
  nghttp2_mem *mem;
1121
1122
55.8k
  mem = context->mem;
1123
55.8k
  room = entry_room(nv->name->len, nv->value->len);
1124
1125
61.6k
  while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
1126
6.82k
         context->hd_table.len > 0) {
1127
5.77k
    size_t idx = context->hd_table.len - 1;
1128
5.77k
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1129
1130
5.77k
    context->hd_table_bufsize -=
1131
5.77k
      entry_room(ent->nv.name->len, ent->nv.value->len);
1132
1133
5.77k
    DEBUGF("hpack: remove item from header table: %s: %s\n",
1134
5.77k
           (char *)ent->nv.name->base, (char *)ent->nv.value->base);
1135
1136
5.77k
    hd_ringbuf_pop_back(&context->hd_table);
1137
5.77k
    if (map) {
1138
0
      hd_map_remove(map, ent);
1139
0
    }
1140
1141
5.77k
    nghttp2_hd_entry_free(ent);
1142
5.77k
    nghttp2_mem_free(mem, ent);
1143
5.77k
  }
1144
1145
55.8k
  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.05k
    return 0;
1149
1.05k
  }
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
8.79k
    hd_map_insert(map, new_ent);
1172
8.79k
  }
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.26k
                                         int name_only) {
1187
1.26k
  search_result res = {token, 0};
1188
1.26k
  int i;
1189
1.26k
  const nghttp2_hd_static_entry *ent;
1190
1191
1.26k
  if (name_only) {
1192
62
    return res;
1193
62
  }
1194
1195
1.20k
  for (i = token;
1196
1.74k
       i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token;
1197
1.50k
       ++i) {
1198
1.50k
    ent = &static_table[i];
1199
1.50k
    if (ent->value.len == nv->valuelen &&
1200
1.16k
        memcmp(ent->value.base, nv->value, nv->valuelen) == 0) {
1201
974
      res.index = i;
1202
974
      res.name_value_match = 1;
1203
974
      return res;
1204
974
    }
1205
1.50k
  }
1206
233
  return res;
1207
1.20k
}
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
32.8k
                                     uint32_t hash) {
1213
32.8k
  search_result res = {-1, 0};
1214
32.8k
  const nghttp2_hd_entry *ent;
1215
32.8k
  int exact_match;
1216
32.8k
  int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
1217
1218
32.8k
  exact_match = 0;
1219
32.8k
  ent = hd_map_find(map, &exact_match, nv, token, hash, name_only);
1220
1221
32.8k
  if (!exact_match && token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1222
1.26k
    return search_static_table(nv, token, name_only);
1223
1.26k
  }
1224
1225
31.5k
  if (ent == NULL) {
1226
8.01k
    return res;
1227
8.01k
  }
1228
1229
23.5k
  res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq +
1230
23.5k
                              NGHTTP2_STATIC_TABLE_LENGTH);
1231
23.5k
  res.name_value_match = exact_match;
1232
1233
23.5k
  return res;
1234
31.5k
}
1235
1236
static void hd_context_shrink_table_size(nghttp2_hd_context *context,
1237
7.12k
                                         nghttp2_hd_map *map) {
1238
7.12k
  nghttp2_mem *mem;
1239
1240
7.12k
  mem = context->mem;
1241
1242
7.97k
  while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
1243
851
         context->hd_table.len > 0) {
1244
851
    size_t idx = context->hd_table.len - 1;
1245
851
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1246
851
    context->hd_table_bufsize -=
1247
851
      entry_room(ent->nv.name->len, ent->nv.value->len);
1248
851
    hd_ringbuf_pop_back(&context->hd_table);
1249
851
    if (map) {
1250
0
      hd_map_remove(map, ent);
1251
0
    }
1252
1253
851
    nghttp2_hd_entry_free(ent);
1254
851
    nghttp2_mem_free(mem, ent);
1255
851
  }
1256
7.12k
}
1257
1258
int nghttp2_hd_deflate_change_table_size(
1259
2.59k
  nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
1260
2.59k
  size_t next_bufsize = nghttp2_min_size(
1261
2.59k
    settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
1262
1263
2.59k
  deflater->ctx.hd_table_bufsize_max = next_bufsize;
1264
1265
2.59k
  deflater->min_hd_table_bufsize_max =
1266
2.59k
    nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
1267
1268
2.59k
  deflater->notify_table_size_change = 1;
1269
1270
2.59k
  hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
1271
2.59k
  return 0;
1272
2.59k
}
1273
1274
int nghttp2_hd_inflate_change_table_size(
1275
104
  nghttp2_hd_inflater *inflater, size_t settings_max_dynamic_table_size) {
1276
104
  switch (inflater->state) {
1277
19
  case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1278
104
  case NGHTTP2_HD_STATE_INFLATE_START:
1279
104
    break;
1280
0
  default:
1281
0
    return NGHTTP2_ERR_INVALID_STATE;
1282
104
  }
1283
1284
104
  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
104
  if (inflater->ctx.hd_table_bufsize_max > settings_max_dynamic_table_size) {
1294
82
    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
82
    inflater->min_hd_table_bufsize_max = settings_max_dynamic_table_size;
1298
1299
82
    inflater->ctx.hd_table_bufsize_max = settings_max_dynamic_table_size;
1300
1301
82
    hd_context_shrink_table_size(&inflater->ctx, NULL);
1302
82
  }
1303
1304
104
  return 0;
1305
104
}
1306
1307
#define INDEX_RANGE_VALID(context, idx)                                        \
1308
0
  ((idx) < (context)->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH)
1309
1310
174k
static size_t get_max_index(nghttp2_hd_context *context) {
1311
174k
  return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
1312
174k
}
1313
1314
173k
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
1315
173k
  assert(INDEX_RANGE_VALID(context, idx));
1316
173k
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1317
72.0k
    return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
1318
72.0k
      ->nv;
1319
101k
  } else {
1320
101k
    const nghttp2_hd_static_entry *ent = &static_table[idx];
1321
101k
    nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name,
1322
101k
                        (nghttp2_rcbuf *)&ent->value, ent->token,
1323
101k
                        NGHTTP2_NV_FLAG_NONE};
1324
101k
    return nv;
1325
101k
  }
1326
173k
}
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
32.7k
                                      const nghttp2_nv *nv, int32_t token) {
1342
32.7k
  if (token == NGHTTP2_TOKEN__PATH || token == NGHTTP2_TOKEN_AGE ||
1343
32.5k
      token == NGHTTP2_TOKEN_CONTENT_LENGTH || token == NGHTTP2_TOKEN_ETAG ||
1344
32.5k
      token == NGHTTP2_TOKEN_IF_MODIFIED_SINCE ||
1345
32.5k
      token == NGHTTP2_TOKEN_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION ||
1346
32.4k
      token == NGHTTP2_TOKEN_SET_COOKIE ||
1347
32.4k
      entry_room(nv->namelen, nv->valuelen) >
1348
32.4k
        deflater->ctx.hd_table_bufsize_max * 3 / 4) {
1349
281
    return NGHTTP2_HD_WITHOUT_INDEXING;
1350
281
  }
1351
1352
32.4k
  return NGHTTP2_HD_WITH_INDEXING;
1353
32.7k
}
1354
1355
static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
1356
32.8k
                      const nghttp2_nv *nv) {
1357
32.8k
  int rv;
1358
32.8k
  search_result res;
1359
32.8k
  nghttp2_ssize idx;
1360
32.8k
  int indexing_mode;
1361
32.8k
  int32_t token;
1362
32.8k
  nghttp2_mem *mem;
1363
32.8k
  uint32_t hash = 0;
1364
1365
32.8k
  DEBUGF("deflatehd: deflating %.*s: %.*s\n", (int)nv->namelen, nv->name,
1366
32.8k
         (int)nv->valuelen, nv->value);
1367
1368
32.8k
  mem = deflater->ctx.mem;
1369
1370
32.8k
  token = lookup_token(nv->name, nv->namelen);
1371
32.8k
  if (token == -1) {
1372
31.2k
    hash = name_hash(nv);
1373
31.2k
  } else if (token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1374
1.31k
    hash = static_table[token].hash;
1375
1.31k
  }
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
32.8k
  indexing_mode = token == NGHTTP2_TOKEN_AUTHORIZATION ||
1382
32.7k
                      (token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
1383
32.7k
                      (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
1384
32.8k
                    ? NGHTTP2_HD_NEVER_INDEXING
1385
32.8k
                    : hd_deflate_decide_indexing(deflater, nv, token);
1386
1387
32.8k
  res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
1388
32.8k
                        &deflater->map, hash);
1389
1390
32.8k
  idx = res.index;
1391
1392
32.8k
  if (res.name_value_match) {
1393
23.8k
    DEBUGF("deflatehd: name/value match index=%td\n", idx);
1394
1395
23.8k
    rv = emit_indexed_block(bufs, (size_t)idx);
1396
23.8k
    if (rv != 0) {
1397
0
      return rv;
1398
0
    }
1399
1400
23.8k
    return 0;
1401
23.8k
  }
1402
1403
8.92k
  if (res.index != -1) {
1404
911
    DEBUGF("deflatehd: name match index=%td\n", res.index);
1405
911
  }
1406
1407
8.92k
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1408
8.79k
    nghttp2_hd_nv hd_nv;
1409
1410
8.79k
    if (idx != -1) {
1411
782
      hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
1412
782
      nghttp2_rcbuf_incref(hd_nv.name);
1413
8.01k
    } else {
1414
8.01k
      rv = nghttp2_rcbuf_new2(&hd_nv.name, nv->name, nv->namelen, mem);
1415
8.01k
      if (rv != 0) {
1416
0
        return rv;
1417
0
      }
1418
8.01k
    }
1419
1420
8.79k
    rv = nghttp2_rcbuf_new2(&hd_nv.value, nv->value, nv->valuelen, mem);
1421
1422
8.79k
    if (rv != 0) {
1423
0
      nghttp2_rcbuf_decref(hd_nv.name);
1424
0
      return rv;
1425
0
    }
1426
1427
8.79k
    hd_nv.token = token;
1428
8.79k
    hd_nv.flags = NGHTTP2_NV_FLAG_NONE;
1429
1430
8.79k
    rv = add_hd_table_incremental(&deflater->ctx, &hd_nv, &deflater->map, hash);
1431
1432
8.79k
    nghttp2_rcbuf_decref(hd_nv.value);
1433
8.79k
    nghttp2_rcbuf_decref(hd_nv.name);
1434
1435
8.79k
    if (rv != 0) {
1436
0
      return NGHTTP2_ERR_HEADER_COMP;
1437
0
    }
1438
8.79k
  }
1439
8.92k
  if (idx == -1) {
1440
8.01k
    rv = emit_newname_block(bufs, nv, indexing_mode);
1441
8.01k
  } else {
1442
911
    rv = emit_indname_block(bufs, (size_t)idx, nv, indexing_mode);
1443
911
  }
1444
8.92k
  if (rv != 0) {
1445
0
    return rv;
1446
0
  }
1447
1448
8.92k
  return 0;
1449
8.92k
}
1450
1451
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
1452
                               nghttp2_bufs *bufs, const nghttp2_nv *nv,
1453
4.68k
                               size_t nvlen) {
1454
4.68k
  size_t i;
1455
4.68k
  int rv = 0;
1456
1457
4.68k
  if (deflater->ctx.bad) {
1458
0
    return NGHTTP2_ERR_HEADER_COMP;
1459
0
  }
1460
1461
4.68k
  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
37.4k
  for (i = 0; i < nvlen; ++i) {
1485
32.8k
    rv = deflate_nv(deflater, bufs, &nv[i]);
1486
32.8k
    if (rv != 0) {
1487
0
      goto fail;
1488
0
    }
1489
32.8k
  }
1490
1491
4.68k
  DEBUGF("deflatehd: all input name/value pairs were deflated\n");
1492
1493
4.68k
  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.68k
}
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
232k
                                           const uint8_t *in) {
1652
232k
  inflater->huffman_encoded = (*in & (1 << 7)) != 0;
1653
232k
}
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
412k
                                         size_t maxlen) {
1672
412k
  nghttp2_ssize rv;
1673
412k
  uint32_t out;
1674
1675
412k
  *rfin = 0;
1676
1677
412k
  rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
1678
412k
                     inflater->shift, in, last, prefix);
1679
1680
412k
  if (rv == -1) {
1681
202
    DEBUGF("inflatehd: integer decoding failed\n");
1682
202
    return NGHTTP2_ERR_HEADER_COMP;
1683
202
  }
1684
1685
412k
  if (out > maxlen) {
1686
1.59k
    DEBUGF("inflatehd: integer exceeded the maximum value %zu\n", maxlen);
1687
1.59k
    return NGHTTP2_ERR_HEADER_COMP;
1688
1.59k
  }
1689
1690
411k
  inflater->left = out;
1691
1692
411k
  DEBUGF("inflatehd: decoded integer is %u\n", out);
1693
1694
411k
  return rv;
1695
412k
}
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
37.6k
                                          const uint8_t *last) {
1713
37.6k
  nghttp2_ssize readlen;
1714
37.6k
  int fin = 0;
1715
37.6k
  if ((size_t)(last - in) >= inflater->left) {
1716
37.3k
    last = in + inflater->left;
1717
37.3k
    fin = 1;
1718
37.3k
  }
1719
37.6k
  readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
1720
37.6k
                                   (size_t)(last - in), fin);
1721
1722
37.6k
  if (readlen < 0) {
1723
39
    DEBUGF("inflatehd: huffman decoding failed\n");
1724
39
    return readlen;
1725
39
  }
1726
37.6k
  if (nghttp2_hd_huff_decode_failure_state(&inflater->huff_decode_ctx)) {
1727
16
    DEBUGF("inflatehd: huffman decoding failed\n");
1728
16
    return NGHTTP2_ERR_HEADER_COMP;
1729
16
  }
1730
1731
37.5k
  inflater->left -= (size_t)readlen;
1732
37.5k
  return readlen;
1733
37.6k
}
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
193k
                                     const uint8_t *last) {
1750
193k
  size_t len = nghttp2_min_size((size_t)(last - in), inflater->left);
1751
1752
193k
  buf->last = nghttp2_cpymem(buf->last, in, len);
1753
1754
193k
  inflater->left -= len;
1755
193k
  return (nghttp2_ssize)len;
1756
193k
}
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
134k
                                      nghttp2_hd_nv *nv_out) {
1764
134k
  nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1765
1766
134k
  emit_header(nv_out, &nv);
1767
134k
}
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
96.0k
                                     nghttp2_hd_nv *nv_out) {
1782
96.0k
  nghttp2_hd_nv nv;
1783
96.0k
  int rv;
1784
1785
96.0k
  if (inflater->no_index) {
1786
2.81k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1787
93.2k
  } else {
1788
93.2k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1789
93.2k
  }
1790
1791
96.0k
  nv.name = inflater->namercbuf;
1792
96.0k
  nv.value = inflater->valuercbuf;
1793
96.0k
  nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
1794
1795
96.0k
  if (inflater->index_required) {
1796
23.1k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1797
1798
23.1k
    if (rv != 0) {
1799
0
      return rv;
1800
0
    }
1801
23.1k
  }
1802
1803
96.0k
  emit_header(nv_out, &nv);
1804
1805
96.0k
  inflater->nv_name_keep = nv.name;
1806
96.0k
  inflater->nv_value_keep = nv.value;
1807
1808
96.0k
  inflater->namercbuf = NULL;
1809
96.0k
  inflater->valuercbuf = NULL;
1810
1811
96.0k
  return 0;
1812
96.0k
}
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
38.2k
                                     nghttp2_hd_nv *nv_out) {
1827
38.2k
  nghttp2_hd_nv nv;
1828
38.2k
  int rv;
1829
1830
38.2k
  nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1831
1832
38.2k
  if (inflater->no_index) {
1833
2.67k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1834
35.5k
  } else {
1835
35.5k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1836
35.5k
  }
1837
1838
38.2k
  nghttp2_rcbuf_incref(nv.name);
1839
1840
38.2k
  nv.value = inflater->valuercbuf;
1841
1842
38.2k
  if (inflater->index_required) {
1843
23.9k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1844
23.9k
    if (rv != 0) {
1845
0
      nghttp2_rcbuf_decref(nv.name);
1846
0
      return NGHTTP2_ERR_NOMEM;
1847
0
    }
1848
23.9k
  }
1849
1850
38.2k
  emit_header(nv_out, &nv);
1851
1852
38.2k
  inflater->nv_name_keep = nv.name;
1853
38.2k
  inflater->nv_value_keep = nv.value;
1854
1855
38.2k
  inflater->valuercbuf = NULL;
1856
1857
38.2k
  return 0;
1858
38.2k
}
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
18.7k
                                     int in_final) {
1878
18.7k
  nghttp2_ssize rv;
1879
18.7k
  nghttp2_hd_nv hd_nv;
1880
1881
18.7k
  rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
1882
18.7k
                                in_final);
1883
1884
18.7k
  if (rv < 0) {
1885
0
    return rv;
1886
0
  }
1887
1888
18.7k
  if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
1889
16.4k
    nv_out->name = hd_nv.name->base;
1890
16.4k
    nv_out->namelen = hd_nv.name->len;
1891
1892
16.4k
    nv_out->value = hd_nv.value->base;
1893
16.4k
    nv_out->valuelen = hd_nv.value->len;
1894
1895
16.4k
    nv_out->flags = hd_nv.flags;
1896
16.4k
  }
1897
1898
18.7k
  return rv;
1899
18.7k
}
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
310k
                                       size_t inlen, int in_final) {
1905
310k
  nghttp2_ssize rv = 0;
1906
310k
  const uint8_t *first = in;
1907
310k
  const uint8_t *last = in + inlen;
1908
310k
  int rfin = 0;
1909
310k
  int busy = 0;
1910
310k
  nghttp2_mem *mem;
1911
1912
310k
  mem = inflater->ctx.mem;
1913
1914
310k
  if (inflater->ctx.bad) {
1915
0
    return NGHTTP2_ERR_HEADER_COMP;
1916
0
  }
1917
1918
310k
  DEBUGF("inflatehd: start state=%d\n", inflater->state);
1919
310k
  hd_inflate_keep_free(inflater);
1920
310k
  *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
1921
957k
  for (; in != last || busy;) {
1922
920k
    busy = 0;
1923
920k
    switch (inflater->state) {
1924
15
    case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1925
15
      if ((*in & 0xe0u) != 0x20u) {
1926
1
        DEBUGF("inflatehd: header table size change was expected, but saw "
1927
1
               "0x%02x as first byte",
1928
1
               *in);
1929
1
        rv = NGHTTP2_ERR_HEADER_COMP;
1930
1
        goto fail;
1931
1
      }
1932
    /* fall through */
1933
35.2k
    case NGHTTP2_HD_STATE_INFLATE_START:
1934
276k
    case NGHTTP2_HD_STATE_OPCODE:
1935
276k
      if ((*in & 0xe0u) == 0x20u) {
1936
5.00k
        DEBUGF("inflatehd: header table size change\n");
1937
5.00k
        if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
1938
39
          DEBUGF("inflatehd: header table size change must appear at the head "
1939
39
                 "of header block\n");
1940
39
          rv = NGHTTP2_ERR_HEADER_COMP;
1941
39
          goto fail;
1942
39
        }
1943
4.96k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1944
4.96k
        inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
1945
271k
      } else if (*in & 0x80u) {
1946
135k
        DEBUGF("inflatehd: indexed repr\n");
1947
135k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1948
135k
        inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1949
136k
      } else {
1950
136k
        if (*in == 0x40u || *in == 0 || *in == 0x10u) {
1951
97.0k
          DEBUGF("inflatehd: literal header repr - new name\n");
1952
97.0k
          inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
1953
97.0k
          inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
1954
97.0k
        } else {
1955
39.3k
          DEBUGF("inflatehd: literal header repr - indexed name\n");
1956
39.3k
          inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
1957
39.3k
          inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1958
39.3k
        }
1959
136k
        inflater->index_required = (*in & 0x40) != 0;
1960
136k
        inflater->no_index = (*in & 0xf0u) == 0x10u;
1961
136k
        DEBUGF("inflatehd: indexing required=%d, no_index=%d\n",
1962
136k
               inflater->index_required, inflater->no_index);
1963
136k
        if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1964
97.0k
          ++in;
1965
97.0k
        }
1966
136k
      }
1967
276k
      inflater->left = 0;
1968
276k
      inflater->shift = 0;
1969
276k
      break;
1970
5.57k
    case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
1971
5.57k
      rfin = 0;
1972
5.57k
      rv = hd_inflate_read_len(
1973
5.57k
        inflater, &rfin, in, last, 5,
1974
5.57k
        nghttp2_min_size(inflater->min_hd_table_bufsize_max,
1975
5.57k
                         inflater->settings_hd_table_bufsize_max));
1976
5.57k
      if (rv < 0) {
1977
420
        goto fail;
1978
420
      }
1979
5.15k
      in += rv;
1980
5.15k
      if (!rfin) {
1981
704
        goto almost_ok;
1982
704
      }
1983
4.45k
      DEBUGF("inflatehd: table_size=%zu\n", inflater->left);
1984
4.45k
      inflater->min_hd_table_bufsize_max = UINT32_MAX;
1985
4.45k
      inflater->ctx.hd_table_bufsize_max = inflater->left;
1986
4.45k
      hd_context_shrink_table_size(&inflater->ctx, NULL);
1987
4.45k
      inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
1988
4.45k
      break;
1989
174k
    case NGHTTP2_HD_STATE_READ_INDEX: {
1990
174k
      size_t prefixlen;
1991
1992
174k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
1993
135k
        prefixlen = 7;
1994
135k
      } else if (inflater->index_required) {
1995
24.4k
        prefixlen = 6;
1996
24.4k
      } else {
1997
15.4k
        prefixlen = 4;
1998
15.4k
      }
1999
2000
174k
      rfin = 0;
2001
174k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
2002
174k
                               get_max_index(&inflater->ctx));
2003
174k
      if (rv < 0) {
2004
729
        goto fail;
2005
729
      }
2006
2007
174k
      in += rv;
2008
2009
174k
      if (!rfin) {
2010
472
        goto almost_ok;
2011
472
      }
2012
2013
173k
      if (inflater->left == 0) {
2014
18
        rv = NGHTTP2_ERR_HEADER_COMP;
2015
18
        goto fail;
2016
18
      }
2017
2018
173k
      DEBUGF("inflatehd: index=%zu\n", inflater->left);
2019
173k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2020
134k
        inflater->index = inflater->left;
2021
134k
        --inflater->index;
2022
2023
134k
        hd_inflate_commit_indexed(inflater, nv_out);
2024
2025
134k
        inflater->state = NGHTTP2_HD_STATE_OPCODE;
2026
134k
        *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2027
134k
        return (nghttp2_ssize)(in - first);
2028
134k
      } else {
2029
39.0k
        inflater->index = inflater->left;
2030
39.0k
        --inflater->index;
2031
2032
39.0k
        inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2033
39.0k
      }
2034
39.0k
      break;
2035
173k
    }
2036
96.9k
    case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
2037
96.9k
      hd_inflate_set_huffman_encoded(inflater, in);
2038
96.9k
      inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
2039
96.9k
      inflater->left = 0;
2040
96.9k
      inflater->shift = 0;
2041
96.9k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2042
    /* Fall through */
2043
97.1k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
2044
97.1k
      rfin = 0;
2045
97.1k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2046
97.1k
      if (rv < 0) {
2047
319
        goto fail;
2048
319
      }
2049
96.8k
      in += rv;
2050
96.8k
      if (!rfin) {
2051
323
        DEBUGF("inflatehd: integer not fully decoded. current=%zu\n",
2052
323
               inflater->left);
2053
2054
323
        goto almost_ok;
2055
323
      }
2056
2057
96.5k
      if (inflater->huffman_encoded) {
2058
16.5k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2059
2060
16.5k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
2061
2062
16.5k
        rv =
2063
16.5k
          nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1, mem);
2064
79.9k
      } else {
2065
79.9k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
2066
79.9k
        rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
2067
79.9k
      }
2068
2069
96.5k
      if (rv != 0) {
2070
0
        goto fail;
2071
0
      }
2072
2073
96.5k
      nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
2074
96.5k
                            inflater->namercbuf->len);
2075
2076
96.5k
      break;
2077
16.5k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
2078
16.5k
      rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
2079
16.5k
      if (rv < 0) {
2080
24
        goto fail;
2081
24
      }
2082
2083
16.5k
      in += rv;
2084
2085
16.5k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2086
2087
16.5k
      if (inflater->left) {
2088
117
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2089
2090
117
        goto almost_ok;
2091
117
      }
2092
2093
16.3k
      *inflater->namebuf.last = '\0';
2094
16.3k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2095
2096
16.3k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2097
2098
16.3k
      break;
2099
79.8k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
2100
79.8k
      rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
2101
79.8k
      if (rv < 0) {
2102
0
        goto fail;
2103
0
      }
2104
2105
79.8k
      in += rv;
2106
2107
79.8k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2108
79.8k
      if (inflater->left) {
2109
140
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2110
2111
140
        goto almost_ok;
2112
140
      }
2113
2114
79.7k
      *inflater->namebuf.last = '\0';
2115
79.7k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2116
2117
79.7k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2118
2119
79.7k
      break;
2120
135k
    case NGHTTP2_HD_STATE_CHECK_VALUELEN:
2121
135k
      hd_inflate_set_huffman_encoded(inflater, in);
2122
135k
      inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
2123
135k
      inflater->left = 0;
2124
135k
      inflater->shift = 0;
2125
135k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2126
    /* Fall through */
2127
135k
    case NGHTTP2_HD_STATE_READ_VALUELEN:
2128
135k
      rfin = 0;
2129
135k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2130
135k
      if (rv < 0) {
2131
328
        goto fail;
2132
328
      }
2133
2134
135k
      in += rv;
2135
2136
135k
      if (!rfin) {
2137
374
        goto almost_ok;
2138
374
      }
2139
2140
134k
      DEBUGF("inflatehd: valuelen=%zu\n", inflater->left);
2141
2142
134k
      if (inflater->huffman_encoded) {
2143
21.1k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2144
2145
21.1k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
2146
2147
21.1k
        rv =
2148
21.1k
          nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1, mem);
2149
113k
      } else {
2150
113k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
2151
2152
113k
        rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
2153
113k
      }
2154
2155
134k
      if (rv != 0) {
2156
0
        goto fail;
2157
0
      }
2158
2159
134k
      nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
2160
134k
                            inflater->valuercbuf->len);
2161
2162
134k
      busy = 1;
2163
2164
134k
      break;
2165
21.1k
    case NGHTTP2_HD_STATE_READ_VALUEHUFF:
2166
21.1k
      rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
2167
21.1k
      if (rv < 0) {
2168
31
        goto fail;
2169
31
      }
2170
2171
21.0k
      in += rv;
2172
2173
21.0k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2174
2175
21.0k
      if (inflater->left) {
2176
172
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2177
2178
172
        goto almost_ok;
2179
172
      }
2180
2181
20.9k
      *inflater->valuebuf.last = '\0';
2182
20.9k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2183
2184
20.9k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2185
8.84k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2186
12.0k
      } else {
2187
12.0k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2188
12.0k
      }
2189
2190
20.9k
      if (rv != 0) {
2191
0
        goto fail;
2192
0
      }
2193
2194
20.9k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2195
20.9k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2196
2197
20.9k
      return (nghttp2_ssize)(in - first);
2198
113k
    case NGHTTP2_HD_STATE_READ_VALUE:
2199
113k
      rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
2200
113k
      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
113k
      in += rv;
2207
2208
113k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2209
2210
113k
      if (inflater->left) {
2211
235
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2212
235
        goto almost_ok;
2213
235
      }
2214
2215
113k
      *inflater->valuebuf.last = '\0';
2216
113k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2217
2218
113k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2219
87.2k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2220
87.2k
      } else {
2221
26.1k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2222
26.1k
      }
2223
2224
113k
      if (rv != 0) {
2225
0
        goto fail;
2226
0
      }
2227
2228
113k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2229
113k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2230
2231
113k
      return (nghttp2_ssize)(in - first);
2232
920k
    }
2233
920k
  }
2234
2235
310k
  assert(in == last);
2236
2237
36.6k
  DEBUGF("inflatehd: all input bytes were processed\n");
2238
2239
36.6k
  if (in_final) {
2240
23.6k
    DEBUGF("inflatehd: in_final set\n");
2241
2242
23.6k
    if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
2243
9.78k
        inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
2244
17
      DEBUGF("inflatehd: unacceptable state=%d\n", inflater->state);
2245
17
      rv = NGHTTP2_ERR_HEADER_COMP;
2246
2247
17
      goto fail;
2248
17
    }
2249
23.6k
    *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
2250
23.6k
  }
2251
36.6k
  return (nghttp2_ssize)(in - first);
2252
2253
2.53k
almost_ok:
2254
2.53k
  if (in_final) {
2255
21
    DEBUGF("inflatehd: input ended prematurely\n");
2256
2257
21
    rv = NGHTTP2_ERR_HEADER_COMP;
2258
2259
21
    goto fail;
2260
21
  }
2261
2.51k
  return (nghttp2_ssize)(in - first);
2262
2263
1.94k
fail:
2264
1.94k
  DEBUGF("inflatehd: error return %td\n", rv);
2265
2266
1.94k
  inflater->ctx.bad = 1;
2267
1.94k
  return rv;
2268
2.53k
}
2269
2270
23.6k
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
2271
23.6k
  hd_inflate_keep_free(inflater);
2272
23.6k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2273
23.6k
  return 0;
2274
23.6k
}
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
}