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
41.6k
static int memeq(const void *s1, const void *s2, size_t n) {
115
41.6k
  return memcmp(s1, s2, n) == 0;
116
41.6k
}
117
118
/*
119
 * This function was generated by genlibtokenlookup.py.  Inspired by
120
 * h2o header lookup.  https://github.com/h2o/h2o
121
 */
122
69.8k
static int32_t lookup_token(const uint8_t *name, size_t namelen) {
123
69.8k
  switch (namelen) {
124
970
  case 2:
125
970
    switch (name[1]) {
126
718
    case 'e':
127
718
      if (memeq("t", name, 1)) {
128
490
        return NGHTTP2_TOKEN_TE;
129
490
      }
130
228
      break;
131
970
    }
132
480
    break;
133
1.80k
  case 3:
134
1.80k
    switch (name[2]) {
135
652
    case 'a':
136
652
      if (memeq("vi", name, 2)) {
137
220
        return NGHTTP2_TOKEN_VIA;
138
220
      }
139
432
      break;
140
437
    case 'e':
141
437
      if (memeq("ag", name, 2)) {
142
194
        return NGHTTP2_TOKEN_AGE;
143
194
      }
144
243
      break;
145
1.80k
    }
146
1.39k
    break;
147
4.64k
  case 4:
148
4.64k
    switch (name[3]) {
149
642
    case 'e':
150
642
      if (memeq("dat", name, 3)) {
151
402
        return NGHTTP2_TOKEN_DATE;
152
402
      }
153
240
      break;
154
492
    case 'g':
155
492
      if (memeq("eta", name, 3)) {
156
222
        return NGHTTP2_TOKEN_ETAG;
157
222
      }
158
270
      break;
159
561
    case 'k':
160
561
      if (memeq("lin", name, 3)) {
161
239
        return NGHTTP2_TOKEN_LINK;
162
239
      }
163
322
      break;
164
682
    case 'm':
165
682
      if (memeq("fro", name, 3)) {
166
356
        return NGHTTP2_TOKEN_FROM;
167
356
      }
168
326
      break;
169
418
    case 't':
170
418
      if (memeq("hos", name, 3)) {
171
194
        return NGHTTP2_TOKEN_HOST;
172
194
      }
173
224
      break;
174
575
    case 'y':
175
575
      if (memeq("var", name, 3)) {
176
226
        return NGHTTP2_TOKEN_VARY;
177
226
      }
178
349
      break;
179
4.64k
    }
180
3.00k
    break;
181
3.00k
  case 5:
182
2.27k
    switch (name[4]) {
183
886
    case 'e':
184
886
      if (memeq("rang", name, 4)) {
185
531
        return NGHTTP2_TOKEN_RANGE;
186
531
      }
187
355
      break;
188
455
    case 'h':
189
455
      if (memeq(":pat", name, 4)) {
190
214
        return NGHTTP2_TOKEN__PATH;
191
214
      }
192
241
      break;
193
531
    case 'w':
194
531
      if (memeq("allo", name, 4)) {
195
199
        return NGHTTP2_TOKEN_ALLOW;
196
199
      }
197
332
      break;
198
2.27k
    }
199
1.33k
    break;
200
2.39k
  case 6:
201
2.39k
    switch (name[5]) {
202
400
    case 'e':
203
400
      if (memeq("cooki", name, 5)) {
204
194
        return NGHTTP2_TOKEN_COOKIE;
205
194
      }
206
206
      break;
207
392
    case 'r':
208
392
      if (memeq("serve", name, 5)) {
209
194
        return NGHTTP2_TOKEN_SERVER;
210
194
      }
211
198
      break;
212
883
    case 't':
213
883
      if (memeq("accep", name, 5)) {
214
386
        return NGHTTP2_TOKEN_ACCEPT;
215
386
      }
216
497
      if (memeq("expec", name, 5)) {
217
282
        return NGHTTP2_TOKEN_EXPECT;
218
282
      }
219
215
      break;
220
2.39k
    }
221
1.33k
    break;
222
3.64k
  case 7:
223
3.64k
    switch (name[6]) {
224
396
    case 'd':
225
396
      if (memeq(":metho", name, 6)) {
226
194
        return NGHTTP2_TOKEN__METHOD;
227
194
      }
228
202
      break;
229
1.32k
    case 'e':
230
1.32k
      if (memeq(":schem", name, 6)) {
231
194
        return NGHTTP2_TOKEN__SCHEME;
232
194
      }
233
1.13k
      if (memeq("upgrad", name, 6)) {
234
292
        return NGHTTP2_TOKEN_UPGRADE;
235
292
      }
236
838
      break;
237
838
    case 'h':
238
536
      if (memeq("refres", name, 6)) {
239
335
        return NGHTTP2_TOKEN_REFRESH;
240
335
      }
241
201
      break;
242
394
    case 'r':
243
394
      if (memeq("refere", name, 6)) {
244
195
        return NGHTTP2_TOKEN_REFERER;
245
195
      }
246
199
      break;
247
610
    case 's':
248
610
      if (memeq(":statu", name, 6)) {
249
194
        return NGHTTP2_TOKEN__STATUS;
250
194
      }
251
416
      if (memeq("expire", name, 6)) {
252
194
        return NGHTTP2_TOKEN_EXPIRES;
253
194
      }
254
222
      break;
255
3.64k
    }
256
2.04k
    break;
257
6.82k
  case 8:
258
6.82k
    switch (name[7]) {
259
738
    case 'e':
260
738
      if (memeq("if-rang", name, 7)) {
261
347
        return NGHTTP2_TOKEN_IF_RANGE;
262
347
      }
263
391
      break;
264
391
    case 'h':
265
390
      if (memeq("if-matc", name, 7)) {
266
194
        return NGHTTP2_TOKEN_IF_MATCH;
267
194
      }
268
196
      break;
269
404
    case 'n':
270
404
      if (memeq("locatio", name, 7)) {
271
202
        return NGHTTP2_TOKEN_LOCATION;
272
202
      }
273
202
      break;
274
4.94k
    case 'y':
275
4.94k
      if (memeq("priorit", name, 7)) {
276
4.73k
        return NGHTTP2_TOKEN_PRIORITY;
277
4.73k
      }
278
216
      break;
279
6.82k
    }
280
1.34k
    break;
281
1.34k
  case 9:
282
1.17k
    switch (name[8]) {
283
812
    case 'l':
284
812
      if (memeq(":protoco", name, 8)) {
285
574
        return NGHTTP2_TOKEN__PROTOCOL;
286
574
      }
287
238
      break;
288
1.17k
    }
289
597
    break;
290
3.84k
  case 10:
291
3.84k
    switch (name[9]) {
292
1.11k
    case 'e':
293
1.11k
      if (memeq("keep-aliv", name, 9)) {
294
374
        return NGHTTP2_TOKEN_KEEP_ALIVE;
295
374
      }
296
742
      if (memeq("set-cooki", name, 9)) {
297
194
        return NGHTTP2_TOKEN_SET_COOKIE;
298
194
      }
299
548
      break;
300
621
    case 'n':
301
621
      if (memeq("connectio", name, 9)) {
302
195
        return NGHTTP2_TOKEN_CONNECTION;
303
195
      }
304
426
      break;
305
875
    case 't':
306
875
      if (memeq("user-agen", name, 9)) {
307
659
        return NGHTTP2_TOKEN_USER_AGENT;
308
659
      }
309
216
      break;
310
657
    case 'y':
311
657
      if (memeq(":authorit", name, 9)) {
312
241
        return NGHTTP2_TOKEN__AUTHORITY;
313
241
      }
314
416
      break;
315
3.84k
    }
316
2.18k
    break;
317
2.18k
  case 11:
318
621
    switch (name[10]) {
319
410
    case 'r':
320
410
      if (memeq("retry-afte", name, 10)) {
321
199
        return NGHTTP2_TOKEN_RETRY_AFTER;
322
199
      }
323
211
      break;
324
621
    }
325
422
    break;
326
1.09k
  case 12:
327
1.09k
    switch (name[11]) {
328
441
    case 'e':
329
441
      if (memeq("content-typ", name, 11)) {
330
210
        return NGHTTP2_TOKEN_CONTENT_TYPE;
331
210
      }
332
231
      break;
333
397
    case 's':
334
397
      if (memeq("max-forward", name, 11)) {
335
194
        return NGHTTP2_TOKEN_MAX_FORWARDS;
336
194
      }
337
203
      break;
338
1.09k
    }
339
688
    break;
340
3.15k
  case 13:
341
3.15k
    switch (name[12]) {
342
541
    case 'd':
343
541
      if (memeq("last-modifie", name, 12)) {
344
316
        return NGHTTP2_TOKEN_LAST_MODIFIED;
345
316
      }
346
225
      break;
347
545
    case 'e':
348
545
      if (memeq("content-rang", name, 12)) {
349
199
        return NGHTTP2_TOKEN_CONTENT_RANGE;
350
199
      }
351
346
      break;
352
417
    case 'h':
353
417
      if (memeq("if-none-matc", name, 12)) {
354
199
        return NGHTTP2_TOKEN_IF_NONE_MATCH;
355
199
      }
356
218
      break;
357
406
    case 'l':
358
406
      if (memeq("cache-contro", name, 12)) {
359
196
        return NGHTTP2_TOKEN_CACHE_CONTROL;
360
196
      }
361
210
      break;
362
513
    case 'n':
363
513
      if (memeq("authorizatio", name, 12)) {
364
302
        return NGHTTP2_TOKEN_AUTHORIZATION;
365
302
      }
366
211
      break;
367
401
    case 's':
368
401
      if (memeq("accept-range", name, 12)) {
369
199
        return NGHTTP2_TOKEN_ACCEPT_RANGES;
370
199
      }
371
202
      break;
372
3.15k
    }
373
1.74k
    break;
374
1.74k
  case 14:
375
1.49k
    switch (name[13]) {
376
675
    case 'h':
377
675
      if (memeq("content-lengt", name, 13)) {
378
194
        return NGHTTP2_TOKEN_CONTENT_LENGTH;
379
194
      }
380
481
      break;
381
552
    case 't':
382
552
      if (memeq("accept-charse", name, 13)) {
383
194
        return NGHTTP2_TOKEN_ACCEPT_CHARSET;
384
194
      }
385
358
      break;
386
1.49k
    }
387
1.11k
    break;
388
1.11k
  case 15:
389
1.09k
    switch (name[14]) {
390
454
    case 'e':
391
454
      if (memeq("accept-languag", name, 14)) {
392
226
        return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
393
226
      }
394
228
      break;
395
425
    case 'g':
396
425
      if (memeq("accept-encodin", name, 14)) {
397
194
        return NGHTTP2_TOKEN_ACCEPT_ENCODING;
398
194
      }
399
231
      break;
400
1.09k
    }
401
673
    break;
402
3.71k
  case 16:
403
3.71k
    switch (name[15]) {
404
1.52k
    case 'e':
405
1.52k
      if (memeq("content-languag", name, 15)) {
406
393
        return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
407
393
      }
408
1.12k
      if (memeq("www-authenticat", name, 15)) {
409
538
        return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
410
538
      }
411
589
      break;
412
589
    case 'g':
413
524
      if (memeq("content-encodin", name, 15)) {
414
271
        return NGHTTP2_TOKEN_CONTENT_ENCODING;
415
271
      }
416
253
      break;
417
725
    case 'n':
418
725
      if (memeq("content-locatio", name, 15)) {
419
194
        return NGHTTP2_TOKEN_CONTENT_LOCATION;
420
194
      }
421
531
      if (memeq("proxy-connectio", name, 15)) {
422
288
        return NGHTTP2_TOKEN_PROXY_CONNECTION;
423
288
      }
424
243
      break;
425
3.71k
    }
426
2.03k
    break;
427
2.03k
  case 17:
428
1.51k
    switch (name[16]) {
429
437
    case 'e':
430
437
      if (memeq("if-modified-sinc", name, 16)) {
431
194
        return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
432
194
      }
433
243
      break;
434
619
    case 'g':
435
619
      if (memeq("transfer-encodin", name, 16)) {
436
378
        return NGHTTP2_TOKEN_TRANSFER_ENCODING;
437
378
      }
438
241
      break;
439
1.51k
    }
440
943
    break;
441
1.16k
  case 18:
442
1.16k
    switch (name[17]) {
443
889
    case 'e':
444
889
      if (memeq("proxy-authenticat", name, 17)) {
445
217
        return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
446
217
      }
447
672
      break;
448
1.16k
    }
449
952
    break;
450
2.29k
  case 19:
451
2.29k
    switch (name[18]) {
452
776
    case 'e':
453
776
      if (memeq("if-unmodified-sinc", name, 18)) {
454
194
        return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
455
194
      }
456
582
      break;
457
1.03k
    case 'n':
458
1.03k
      if (memeq("content-dispositio", name, 18)) {
459
199
        return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
460
199
      }
461
833
      if (memeq("proxy-authorizatio", name, 18)) {
462
603
        return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
463
603
      }
464
230
      break;
465
2.29k
    }
466
1.29k
    break;
467
1.29k
  case 25:
468
771
    switch (name[24]) {
469
558
    case 'y':
470
558
      if (memeq("strict-transport-securit", name, 24)) {
471
334
        return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
472
334
      }
473
224
      break;
474
771
    }
475
437
    break;
476
803
  case 27:
477
803
    switch (name[26]) {
478
541
    case 'n':
479
541
      if (memeq("access-control-allow-origi", name, 26)) {
480
319
        return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
481
319
      }
482
222
      break;
483
803
    }
484
484
    break;
485
69.8k
  }
486
49.0k
  return -1;
487
69.8k
}
488
489
22.5k
void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
490
22.5k
  ent->nv = *nv;
491
22.5k
  ent->cnv.name = nv->name->base;
492
22.5k
  ent->cnv.namelen = nv->name->len;
493
22.5k
  ent->cnv.value = nv->value->base;
494
22.5k
  ent->cnv.valuelen = nv->value->len;
495
22.5k
  ent->cnv.flags = nv->flags;
496
22.5k
  ent->next = NULL;
497
22.5k
  ent->hash = 0;
498
499
22.5k
  nghttp2_rcbuf_incref(ent->nv.name);
500
22.5k
  nghttp2_rcbuf_incref(ent->nv.value);
501
22.5k
}
502
503
22.5k
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
504
22.5k
  nghttp2_rcbuf_decref(ent->nv.value);
505
22.5k
  nghttp2_rcbuf_decref(ent->nv.name);
506
22.5k
}
507
508
0
static int name_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
509
0
  return a->name->len == b->namelen &&
510
0
         memeq(a->name->base, b->name, b->namelen);
511
0
}
512
513
0
static int value_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
514
0
  return a->value->len == b->valuelen &&
515
0
         memeq(a->value->base, b->value, b->valuelen);
516
0
}
517
518
0
static uint32_t name_hash(const nghttp2_nv *nv) {
519
  /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
520
0
  uint32_t h = 2166136261u;
521
0
  size_t i;
522
523
0
  for (i = 0; i < nv->namelen; ++i) {
524
0
    h ^= nv->name[i];
525
0
    h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
526
0
  }
527
528
0
  return h;
529
0
}
530
531
12.4k
static void hd_map_init(nghttp2_hd_map *map) {
532
12.4k
  memset(map, 0, sizeof(nghttp2_hd_map));
533
12.4k
}
534
535
0
static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
536
0
  nghttp2_hd_entry **bucket;
537
538
0
  bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
539
540
0
  if (*bucket == NULL) {
541
0
    *bucket = ent;
542
0
    return;
543
0
  }
544
545
  /* lower index is linked near the root */
546
0
  ent->next = *bucket;
547
0
  *bucket = ent;
548
0
}
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
0
                                     uint32_t hash, int name_only) {
553
0
  nghttp2_hd_entry *p;
554
0
  nghttp2_hd_entry *res = NULL;
555
556
0
  *exact_match = 0;
557
558
0
  for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) {
559
0
    if (token != p->nv.token ||
560
0
        (token == -1 && (hash != p->hash || !name_eq(&p->nv, nv)))) {
561
0
      continue;
562
0
    }
563
0
    if (!res) {
564
0
      res = p;
565
0
      if (name_only) {
566
0
        break;
567
0
      }
568
0
    }
569
0
    if (value_eq(&p->nv, nv)) {
570
0
      res = p;
571
0
      *exact_match = 1;
572
0
      break;
573
0
    }
574
0
  }
575
576
0
  return res;
577
0
}
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
24.9k
                           nghttp2_mem *mem) {
597
24.9k
  size_t size;
598
24.9k
  const size_t max_size = SIZE_MAX / sizeof(nghttp2_hd_entry *);
599
600
24.9k
  if (bufsize > max_size) {
601
0
    return NGHTTP2_ERR_NOMEM;
602
0
  }
603
604
199k
  for (size = 1; size < bufsize; size <<= 1)
605
174k
    ;
606
607
24.9k
  if (size > max_size) {
608
0
    return NGHTTP2_ERR_NOMEM;
609
0
  }
610
611
24.9k
  ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
612
24.9k
  if (ringbuf->buffer == NULL) {
613
0
    return NGHTTP2_ERR_NOMEM;
614
0
  }
615
24.9k
  ringbuf->mask = size - 1;
616
24.9k
  ringbuf->first = 0;
617
24.9k
  ringbuf->len = 0;
618
24.9k
  return 0;
619
24.9k
}
620
621
static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
622
56.3k
                                        size_t idx) {
623
56.3k
  assert(idx < ringbuf->len);
624
56.3k
  return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
625
56.3k
}
626
627
static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
628
22.5k
                              nghttp2_mem *mem) {
629
22.5k
  size_t i;
630
22.5k
  size_t size;
631
22.5k
  nghttp2_hd_entry **buffer;
632
633
22.5k
  if (ringbuf->mask + 1 >= bufsize) {
634
22.5k
    return 0;
635
22.5k
  }
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
24.9k
static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
653
24.9k
  size_t i;
654
24.9k
  if (ringbuf == NULL) {
655
0
    return;
656
0
  }
657
41.9k
  for (i = 0; i < ringbuf->len; ++i) {
658
17.0k
    nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
659
660
17.0k
    nghttp2_hd_entry_free(ent);
661
17.0k
    nghttp2_mem_free(mem, ent);
662
17.0k
  }
663
24.9k
  nghttp2_mem_free(mem, ringbuf->buffer);
664
24.9k
}
665
666
static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
667
22.5k
                                 nghttp2_hd_entry *ent, nghttp2_mem *mem) {
668
22.5k
  int rv;
669
670
22.5k
  rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
671
672
22.5k
  if (rv != 0) {
673
0
    return rv;
674
0
  }
675
676
22.5k
  ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
677
22.5k
  ++ringbuf->len;
678
679
22.5k
  return 0;
680
22.5k
}
681
682
5.51k
static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
683
5.51k
  assert(ringbuf->len > 0);
684
5.51k
  --ringbuf->len;
685
5.51k
}
686
687
24.9k
static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
688
24.9k
  int rv;
689
24.9k
  context->mem = mem;
690
24.9k
  context->bad = 0;
691
24.9k
  context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
692
24.9k
  rv = hd_ringbuf_init(
693
24.9k
    &context->hd_table,
694
24.9k
    context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
695
24.9k
  if (rv != 0) {
696
0
    return rv;
697
0
  }
698
699
24.9k
  context->hd_table_bufsize = 0;
700
24.9k
  context->next_seq = 0;
701
702
24.9k
  return 0;
703
24.9k
}
704
705
24.9k
static void hd_context_free(nghttp2_hd_context *context) {
706
24.9k
  hd_ringbuf_free(&context->hd_table, context->mem);
707
24.9k
}
708
709
0
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
710
0
  return nghttp2_hd_deflate_init2(
711
0
    deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
712
0
}
713
714
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
715
                             size_t max_deflate_dynamic_table_size,
716
12.4k
                             nghttp2_mem *mem) {
717
12.4k
  int rv;
718
12.4k
  rv = hd_context_init(&deflater->ctx, mem);
719
12.4k
  if (rv != 0) {
720
0
    return rv;
721
0
  }
722
723
12.4k
  hd_map_init(&deflater->map);
724
725
12.4k
  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
12.4k
  } else {
729
12.4k
    deflater->notify_table_size_change = 0;
730
12.4k
  }
731
732
12.4k
  deflater->deflate_hd_table_bufsize_max = max_deflate_dynamic_table_size;
733
12.4k
  deflater->min_hd_table_bufsize_max = UINT32_MAX;
734
735
12.4k
  return 0;
736
12.4k
}
737
738
12.4k
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
739
12.4k
  int rv;
740
741
12.4k
  rv = hd_context_init(&inflater->ctx, mem);
742
12.4k
  if (rv != 0) {
743
0
    goto fail;
744
0
  }
745
746
12.4k
  inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
747
12.4k
  inflater->min_hd_table_bufsize_max = UINT32_MAX;
748
749
12.4k
  inflater->nv_name_keep = NULL;
750
12.4k
  inflater->nv_value_keep = NULL;
751
752
12.4k
  inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
753
12.4k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
754
755
12.4k
  nghttp2_buf_init(&inflater->namebuf);
756
12.4k
  nghttp2_buf_init(&inflater->valuebuf);
757
758
12.4k
  inflater->namercbuf = NULL;
759
12.4k
  inflater->valuercbuf = NULL;
760
761
12.4k
  inflater->huffman_encoded = 0;
762
12.4k
  inflater->index = 0;
763
12.4k
  inflater->left = 0;
764
12.4k
  inflater->shift = 0;
765
12.4k
  inflater->index_required = 0;
766
12.4k
  inflater->no_index = 0;
767
768
12.4k
  return 0;
769
770
0
fail:
771
0
  return rv;
772
12.4k
}
773
774
241k
static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
775
241k
  nghttp2_rcbuf_decref(inflater->nv_value_keep);
776
241k
  nghttp2_rcbuf_decref(inflater->nv_name_keep);
777
778
241k
  inflater->nv_value_keep = NULL;
779
241k
  inflater->nv_name_keep = NULL;
780
241k
}
781
782
12.4k
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
783
12.4k
  hd_context_free(&deflater->ctx);
784
12.4k
}
785
786
12.4k
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
787
12.4k
  hd_inflate_keep_free(inflater);
788
789
12.4k
  nghttp2_rcbuf_decref(inflater->valuercbuf);
790
12.4k
  nghttp2_rcbuf_decref(inflater->namercbuf);
791
792
12.4k
  hd_context_free(&inflater->ctx);
793
12.4k
}
794
795
29.0k
static size_t entry_room(size_t namelen, size_t valuelen) {
796
29.0k
  return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
797
29.0k
}
798
799
186k
static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
800
186k
  DEBUGF("inflatehd: header emission: %s: %s\n", nv->name->base,
801
186k
         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
186k
  *nv_out = *nv;
805
186k
}
806
807
0
static size_t count_encoded_length(size_t n, size_t prefix) {
808
0
  size_t k = (size_t)((1 << prefix) - 1);
809
0
  size_t len = 0;
810
811
0
  if (n < k) {
812
0
    return 1;
813
0
  }
814
815
0
  n -= k;
816
0
  ++len;
817
818
0
  for (; n >= 128; n >>= 7, ++len)
819
0
    ;
820
821
0
  return len + 1;
822
0
}
823
824
0
static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
825
0
  size_t k = (size_t)((1 << prefix) - 1);
826
0
  uint8_t *begin = buf;
827
828
0
  *buf = (uint8_t)(*buf & ~k);
829
830
0
  if (n < k) {
831
0
    *buf = (uint8_t)(*buf | n);
832
0
    return 1;
833
0
  }
834
835
0
  *buf = (uint8_t)(*buf | k);
836
0
  ++buf;
837
838
0
  n -= k;
839
840
0
  for (; n >= 128; n >>= 7) {
841
0
    *buf++ = (uint8_t)((1 << 7) | (n & 0x7f));
842
0
  }
843
844
0
  *buf++ = (uint8_t)n;
845
846
0
  return (size_t)(buf - begin);
847
0
}
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
286k
                                   size_t prefix) {
870
286k
  uint32_t k = (uint8_t)((1 << prefix) - 1);
871
286k
  uint32_t n = initial;
872
286k
  const uint8_t *start = in;
873
874
286k
  *shift_ptr = 0;
875
286k
  *fin = 0;
876
877
286k
  if (n == 0) {
878
285k
    if ((*in & k) != k) {
879
278k
      *res = (*in) & k;
880
278k
      *fin = 1;
881
278k
      return 1;
882
278k
    }
883
884
6.89k
    n = k;
885
886
6.89k
    if (++in == last) {
887
130
      *res = n;
888
130
      return (nghttp2_ssize)(in - start);
889
130
    }
890
6.89k
  }
891
892
21.2k
  for (; in != last; ++in, shift += 7) {
893
19.9k
    uint32_t add = *in & 0x7f;
894
895
19.9k
    if (shift >= 32) {
896
26
      DEBUGF("inflate: shift exponent overflow\n");
897
26
      return -1;
898
26
    }
899
900
19.9k
    if ((UINT32_MAX >> shift) < add) {
901
44
      DEBUGF("inflate: integer overflow on shift\n");
902
44
      return -1;
903
44
    }
904
905
19.8k
    add <<= shift;
906
907
19.8k
    if (UINT32_MAX - add < n) {
908
42
      DEBUGF("inflate: integer overflow on addition\n");
909
42
      return -1;
910
42
    }
911
912
19.8k
    n += add;
913
914
19.8k
    if ((*in & (1 << 7)) == 0) {
915
6.24k
      break;
916
6.24k
    }
917
19.8k
  }
918
919
7.51k
  *shift_ptr = shift;
920
921
7.51k
  if (in == last) {
922
1.26k
    *res = n;
923
1.26k
    return (nghttp2_ssize)(in - start);
924
1.26k
  }
925
926
6.24k
  *res = n;
927
6.24k
  *fin = 1;
928
6.24k
  return (nghttp2_ssize)(in + 1 - start);
929
7.51k
}
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
0
static int emit_indexed_block(nghttp2_bufs *bufs, size_t idx) {
960
0
  int rv;
961
0
  size_t blocklen;
962
0
  uint8_t sb[16];
963
0
  uint8_t *bufp;
964
965
0
  blocklen = count_encoded_length(idx + 1, 7);
966
967
0
  DEBUGF("deflatehd: emit indexed index=%zu, %zu bytes\n", idx, blocklen);
968
969
0
  if (sizeof(sb) < blocklen) {
970
0
    return NGHTTP2_ERR_HEADER_COMP;
971
0
  }
972
973
0
  bufp = sb;
974
0
  *bufp = 0x80u;
975
0
  encode_length(bufp, idx + 1, 7);
976
977
0
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
978
0
  if (rv != 0) {
979
0
    return rv;
980
0
  }
981
982
0
  return 0;
983
0
}
984
985
0
static int emit_string(nghttp2_bufs *bufs, const uint8_t *str, size_t len) {
986
0
  int rv;
987
0
  uint8_t sb[16];
988
0
  uint8_t *bufp;
989
0
  size_t blocklen;
990
0
  size_t enclen;
991
0
  int huffman = 0;
992
993
0
  enclen = nghttp2_hd_huff_encode_count(str, len);
994
995
0
  if (enclen < len) {
996
0
    huffman = 1;
997
0
  } else {
998
0
    enclen = len;
999
0
  }
1000
1001
0
  blocklen = count_encoded_length(enclen, 7);
1002
1003
0
  DEBUGF("deflatehd: emit string str=%.*s, length=%zu, huffman=%d, "
1004
0
         "encoded_length=%zu\n",
1005
0
         (int)len, (const char *)str, len, huffman, enclen);
1006
1007
0
  if (sizeof(sb) < blocklen) {
1008
0
    return NGHTTP2_ERR_HEADER_COMP;
1009
0
  }
1010
1011
0
  bufp = sb;
1012
0
  *bufp = huffman ? 1 << 7 : 0;
1013
0
  encode_length(bufp, enclen, 7);
1014
1015
0
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1016
0
  if (rv != 0) {
1017
0
    return rv;
1018
0
  }
1019
1020
0
  if (huffman) {
1021
0
    rv = nghttp2_hd_huff_encode(bufs, str, len);
1022
0
  } else {
1023
0
    assert(enclen == len);
1024
0
    rv = nghttp2_bufs_add(bufs, str, len);
1025
0
  }
1026
1027
0
  return rv;
1028
0
}
1029
1030
0
static uint8_t pack_first_byte(int indexing_mode) {
1031
0
  switch (indexing_mode) {
1032
0
  case NGHTTP2_HD_WITH_INDEXING:
1033
0
    return 0x40u;
1034
0
  case NGHTTP2_HD_WITHOUT_INDEXING:
1035
0
    return 0;
1036
0
  case NGHTTP2_HD_NEVER_INDEXING:
1037
0
    return 0x10u;
1038
0
  default:
1039
0
    assert(0);
1040
0
  }
1041
  /* This is required to compile with android NDK r10d +
1042
     --enable-werror */
1043
0
  return 0;
1044
0
}
1045
1046
static int emit_indname_block(nghttp2_bufs *bufs, size_t idx,
1047
0
                              const nghttp2_nv *nv, int indexing_mode) {
1048
0
  int rv;
1049
0
  uint8_t *bufp;
1050
0
  size_t blocklen;
1051
0
  uint8_t sb[16];
1052
0
  size_t prefixlen;
1053
1054
0
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1055
0
    prefixlen = 6;
1056
0
  } else {
1057
0
    prefixlen = 4;
1058
0
  }
1059
1060
0
  DEBUGF("deflatehd: emit indname index=%zu, valuelen=%zu, indexing_mode=%d\n",
1061
0
         idx, nv->valuelen, indexing_mode);
1062
1063
0
  blocklen = count_encoded_length(idx + 1, prefixlen);
1064
1065
0
  if (sizeof(sb) < blocklen) {
1066
0
    return NGHTTP2_ERR_HEADER_COMP;
1067
0
  }
1068
1069
0
  bufp = sb;
1070
1071
0
  *bufp = pack_first_byte(indexing_mode);
1072
1073
0
  encode_length(bufp, idx + 1, prefixlen);
1074
1075
0
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1076
0
  if (rv != 0) {
1077
0
    return rv;
1078
0
  }
1079
1080
0
  rv = emit_string(bufs, nv->value, nv->valuelen);
1081
0
  if (rv != 0) {
1082
0
    return rv;
1083
0
  }
1084
1085
0
  return 0;
1086
0
}
1087
1088
static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
1089
0
                              int indexing_mode) {
1090
0
  int rv;
1091
1092
0
  DEBUGF(
1093
0
    "deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
1094
0
    nv->namelen, nv->valuelen, indexing_mode);
1095
1096
0
  rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
1097
0
  if (rv != 0) {
1098
0
    return rv;
1099
0
  }
1100
1101
0
  rv = emit_string(bufs, nv->name, nv->namelen);
1102
0
  if (rv != 0) {
1103
0
    return rv;
1104
0
  }
1105
1106
0
  rv = emit_string(bufs, nv->value, nv->valuelen);
1107
0
  if (rv != 0) {
1108
0
    return rv;
1109
0
  }
1110
1111
0
  return 0;
1112
0
}
1113
1114
static int add_hd_table_incremental(nghttp2_hd_context *context,
1115
                                    nghttp2_hd_nv *nv, nghttp2_hd_map *map,
1116
23.4k
                                    uint32_t hash) {
1117
23.4k
  int rv;
1118
23.4k
  nghttp2_hd_entry *new_ent;
1119
23.4k
  size_t room;
1120
23.4k
  nghttp2_mem *mem;
1121
1122
23.4k
  mem = context->mem;
1123
23.4k
  room = entry_room(nv->name->len, nv->value->len);
1124
1125
28.3k
  while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
1126
5.78k
         context->hd_table.len > 0) {
1127
4.83k
    size_t idx = context->hd_table.len - 1;
1128
4.83k
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1129
1130
4.83k
    context->hd_table_bufsize -=
1131
4.83k
      entry_room(ent->nv.name->len, ent->nv.value->len);
1132
1133
4.83k
    DEBUGF("hpack: remove item from header table: %s: %s\n",
1134
4.83k
           (char *)ent->nv.name->base, (char *)ent->nv.value->base);
1135
1136
4.83k
    hd_ringbuf_pop_back(&context->hd_table);
1137
4.83k
    if (map) {
1138
0
      hd_map_remove(map, ent);
1139
0
    }
1140
1141
4.83k
    nghttp2_hd_entry_free(ent);
1142
4.83k
    nghttp2_mem_free(mem, ent);
1143
4.83k
  }
1144
1145
23.4k
  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
950
    return 0;
1149
950
  }
1150
1151
22.5k
  new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
1152
22.5k
  if (new_ent == NULL) {
1153
0
    return NGHTTP2_ERR_NOMEM;
1154
0
  }
1155
1156
22.5k
  nghttp2_hd_entry_init(new_ent, nv);
1157
1158
22.5k
  rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
1159
1160
22.5k
  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
22.5k
  new_ent->seq = context->next_seq++;
1168
22.5k
  new_ent->hash = hash;
1169
1170
22.5k
  if (map) {
1171
0
    hd_map_insert(map, new_ent);
1172
0
  }
1173
1174
22.5k
  context->hd_table_bufsize += room;
1175
1176
22.5k
  return 0;
1177
22.5k
}
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
0
                                         int name_only) {
1187
0
  search_result res = {token, 0};
1188
0
  int i;
1189
0
  const nghttp2_hd_static_entry *ent;
1190
1191
0
  if (name_only) {
1192
0
    return res;
1193
0
  }
1194
1195
0
  for (i = token;
1196
0
       i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token;
1197
0
       ++i) {
1198
0
    ent = &static_table[i];
1199
0
    if (ent->value.len == nv->valuelen &&
1200
0
        memcmp(ent->value.base, nv->value, nv->valuelen) == 0) {
1201
0
      res.index = i;
1202
0
      res.name_value_match = 1;
1203
0
      return res;
1204
0
    }
1205
0
  }
1206
0
  return res;
1207
0
}
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
0
                                     uint32_t hash) {
1213
0
  search_result res = {-1, 0};
1214
0
  const nghttp2_hd_entry *ent;
1215
0
  int exact_match;
1216
0
  int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
1217
1218
0
  exact_match = 0;
1219
0
  ent = hd_map_find(map, &exact_match, nv, token, hash, name_only);
1220
1221
0
  if (!exact_match && token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1222
0
    return search_static_table(nv, token, name_only);
1223
0
  }
1224
1225
0
  if (ent == NULL) {
1226
0
    return res;
1227
0
  }
1228
1229
0
  res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq +
1230
0
                              NGHTTP2_STATIC_TABLE_LENGTH);
1231
0
  res.name_value_match = exact_match;
1232
1233
0
  return res;
1234
0
}
1235
1236
static void hd_context_shrink_table_size(nghttp2_hd_context *context,
1237
4.65k
                                         nghttp2_hd_map *map) {
1238
4.65k
  nghttp2_mem *mem;
1239
1240
4.65k
  mem = context->mem;
1241
1242
5.32k
  while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
1243
673
         context->hd_table.len > 0) {
1244
673
    size_t idx = context->hd_table.len - 1;
1245
673
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1246
673
    context->hd_table_bufsize -=
1247
673
      entry_room(ent->nv.name->len, ent->nv.value->len);
1248
673
    hd_ringbuf_pop_back(&context->hd_table);
1249
673
    if (map) {
1250
0
      hd_map_remove(map, ent);
1251
0
    }
1252
1253
673
    nghttp2_hd_entry_free(ent);
1254
673
    nghttp2_mem_free(mem, ent);
1255
673
  }
1256
4.65k
}
1257
1258
int nghttp2_hd_deflate_change_table_size(
1259
1.84k
  nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
1260
1.84k
  size_t next_bufsize = nghttp2_min_size(
1261
1.84k
    settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
1262
1263
1.84k
  deflater->ctx.hd_table_bufsize_max = next_bufsize;
1264
1265
1.84k
  deflater->min_hd_table_bufsize_max =
1266
1.84k
    nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
1267
1268
1.84k
  deflater->notify_table_size_change = 1;
1269
1270
1.84k
  hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
1271
1.84k
  return 0;
1272
1.84k
}
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
117k
static size_t get_max_index(nghttp2_hd_context *context) {
1311
117k
  return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
1312
117k
}
1313
1314
116k
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
1315
116k
  assert(INDEX_RANGE_VALID(context, idx));
1316
116k
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1317
33.8k
    return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
1318
33.8k
      ->nv;
1319
82.7k
  } else {
1320
82.7k
    const nghttp2_hd_static_entry *ent = &static_table[idx];
1321
82.7k
    nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name,
1322
82.7k
                        (nghttp2_rcbuf *)&ent->value, ent->token,
1323
82.7k
                        NGHTTP2_NV_FLAG_NONE};
1324
82.7k
    return nv;
1325
82.7k
  }
1326
116k
}
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
0
                                      const nghttp2_nv *nv, int32_t token) {
1342
0
  if (token == NGHTTP2_TOKEN__PATH || token == NGHTTP2_TOKEN_AGE ||
1343
0
      token == NGHTTP2_TOKEN_CONTENT_LENGTH || token == NGHTTP2_TOKEN_ETAG ||
1344
0
      token == NGHTTP2_TOKEN_IF_MODIFIED_SINCE ||
1345
0
      token == NGHTTP2_TOKEN_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION ||
1346
0
      token == NGHTTP2_TOKEN_SET_COOKIE ||
1347
0
      entry_room(nv->namelen, nv->valuelen) >
1348
0
        deflater->ctx.hd_table_bufsize_max * 3 / 4) {
1349
0
    return NGHTTP2_HD_WITHOUT_INDEXING;
1350
0
  }
1351
1352
0
  return NGHTTP2_HD_WITH_INDEXING;
1353
0
}
1354
1355
static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
1356
0
                      const nghttp2_nv *nv) {
1357
0
  int rv;
1358
0
  search_result res;
1359
0
  nghttp2_ssize idx;
1360
0
  int indexing_mode;
1361
0
  int32_t token;
1362
0
  nghttp2_mem *mem;
1363
0
  uint32_t hash = 0;
1364
1365
0
  DEBUGF("deflatehd: deflating %.*s: %.*s\n", (int)nv->namelen, nv->name,
1366
0
         (int)nv->valuelen, nv->value);
1367
1368
0
  mem = deflater->ctx.mem;
1369
1370
0
  token = lookup_token(nv->name, nv->namelen);
1371
0
  if (token == -1) {
1372
0
    hash = name_hash(nv);
1373
0
  } else if (token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1374
0
    hash = static_table[token].hash;
1375
0
  }
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
0
  indexing_mode = token == NGHTTP2_TOKEN_AUTHORIZATION ||
1382
0
                      (token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
1383
0
                      (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
1384
0
                    ? NGHTTP2_HD_NEVER_INDEXING
1385
0
                    : hd_deflate_decide_indexing(deflater, nv, token);
1386
1387
0
  res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
1388
0
                        &deflater->map, hash);
1389
1390
0
  idx = res.index;
1391
1392
0
  if (res.name_value_match) {
1393
0
    DEBUGF("deflatehd: name/value match index=%td\n", idx);
1394
1395
0
    rv = emit_indexed_block(bufs, (size_t)idx);
1396
0
    if (rv != 0) {
1397
0
      return rv;
1398
0
    }
1399
1400
0
    return 0;
1401
0
  }
1402
1403
0
  if (res.index != -1) {
1404
0
    DEBUGF("deflatehd: name match index=%td\n", res.index);
1405
0
  }
1406
1407
0
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1408
0
    nghttp2_hd_nv hd_nv;
1409
1410
0
    if (idx != -1) {
1411
0
      hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
1412
0
      nghttp2_rcbuf_incref(hd_nv.name);
1413
0
    } else {
1414
0
      rv = nghttp2_rcbuf_new2(&hd_nv.name, nv->name, nv->namelen, mem);
1415
0
      if (rv != 0) {
1416
0
        return rv;
1417
0
      }
1418
0
    }
1419
1420
0
    rv = nghttp2_rcbuf_new2(&hd_nv.value, nv->value, nv->valuelen, mem);
1421
1422
0
    if (rv != 0) {
1423
0
      nghttp2_rcbuf_decref(hd_nv.name);
1424
0
      return rv;
1425
0
    }
1426
1427
0
    hd_nv.token = token;
1428
0
    hd_nv.flags = NGHTTP2_NV_FLAG_NONE;
1429
1430
0
    rv = add_hd_table_incremental(&deflater->ctx, &hd_nv, &deflater->map, hash);
1431
1432
0
    nghttp2_rcbuf_decref(hd_nv.value);
1433
0
    nghttp2_rcbuf_decref(hd_nv.name);
1434
1435
0
    if (rv != 0) {
1436
0
      return NGHTTP2_ERR_HEADER_COMP;
1437
0
    }
1438
0
  }
1439
0
  if (idx == -1) {
1440
0
    rv = emit_newname_block(bufs, nv, indexing_mode);
1441
0
  } else {
1442
0
    rv = emit_indname_block(bufs, (size_t)idx, nv, indexing_mode);
1443
0
  }
1444
0
  if (rv != 0) {
1445
0
    return rv;
1446
0
  }
1447
1448
0
  return 0;
1449
0
}
1450
1451
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
1452
                               nghttp2_bufs *bufs, const nghttp2_nv *nv,
1453
0
                               size_t nvlen) {
1454
0
  size_t i;
1455
0
  int rv = 0;
1456
1457
0
  if (deflater->ctx.bad) {
1458
0
    return NGHTTP2_ERR_HEADER_COMP;
1459
0
  }
1460
1461
0
  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
0
  for (i = 0; i < nvlen; ++i) {
1485
0
    rv = deflate_nv(deflater, bufs, &nv[i]);
1486
0
    if (rv != 0) {
1487
0
      goto fail;
1488
0
    }
1489
0
  }
1490
1491
0
  DEBUGF("deflatehd: all input name/value pairs were deflated\n");
1492
1493
0
  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
0
}
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
164k
                                           const uint8_t *in) {
1652
164k
  inflater->huffman_encoded = (*in & (1 << 7)) != 0;
1653
164k
}
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
286k
                                         size_t maxlen) {
1672
286k
  nghttp2_ssize rv;
1673
286k
  uint32_t out;
1674
1675
286k
  *rfin = 0;
1676
1677
286k
  rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
1678
286k
                     inflater->shift, in, last, prefix);
1679
1680
286k
  if (rv == -1) {
1681
112
    DEBUGF("inflatehd: integer decoding failed\n");
1682
112
    return NGHTTP2_ERR_HEADER_COMP;
1683
112
  }
1684
1685
285k
  if (out > maxlen) {
1686
836
    DEBUGF("inflatehd: integer exceeded the maximum value %zu\n", maxlen);
1687
836
    return NGHTTP2_ERR_HEADER_COMP;
1688
836
  }
1689
1690
285k
  inflater->left = out;
1691
1692
285k
  DEBUGF("inflatehd: decoded integer is %u\n", out);
1693
1694
285k
  return rv;
1695
285k
}
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
20.4k
                                          const uint8_t *last) {
1713
20.4k
  nghttp2_ssize readlen;
1714
20.4k
  int fin = 0;
1715
20.4k
  if ((size_t)(last - in) >= inflater->left) {
1716
20.2k
    last = in + inflater->left;
1717
20.2k
    fin = 1;
1718
20.2k
  }
1719
20.4k
  readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
1720
20.4k
                                   (size_t)(last - in), fin);
1721
1722
20.4k
  if (readlen < 0) {
1723
34
    DEBUGF("inflatehd: huffman decoding failed\n");
1724
34
    return readlen;
1725
34
  }
1726
20.3k
  if (nghttp2_hd_huff_decode_failure_state(&inflater->huff_decode_ctx)) {
1727
12
    DEBUGF("inflatehd: huffman decoding failed\n");
1728
12
    return NGHTTP2_ERR_HEADER_COMP;
1729
12
  }
1730
1731
20.3k
  inflater->left -= (size_t)readlen;
1732
20.3k
  return readlen;
1733
20.3k
}
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
143k
                                     const uint8_t *last) {
1750
143k
  size_t len = nghttp2_min_size((size_t)(last - in), inflater->left);
1751
1752
143k
  buf->last = nghttp2_cpymem(buf->last, in, len);
1753
1754
143k
  inflater->left -= len;
1755
143k
  return (nghttp2_ssize)len;
1756
143k
}
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
92.6k
                                      nghttp2_hd_nv *nv_out) {
1764
92.6k
  nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1765
1766
92.6k
  emit_header(nv_out, &nv);
1767
92.6k
}
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
69.8k
                                     nghttp2_hd_nv *nv_out) {
1782
69.8k
  nghttp2_hd_nv nv;
1783
69.8k
  int rv;
1784
1785
69.8k
  if (inflater->no_index) {
1786
2.49k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1787
67.3k
  } else {
1788
67.3k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1789
67.3k
  }
1790
1791
69.8k
  nv.name = inflater->namercbuf;
1792
69.8k
  nv.value = inflater->valuercbuf;
1793
69.8k
  nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
1794
1795
69.8k
  if (inflater->index_required) {
1796
10.2k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1797
1798
10.2k
    if (rv != 0) {
1799
0
      return rv;
1800
0
    }
1801
10.2k
  }
1802
1803
69.8k
  emit_header(nv_out, &nv);
1804
1805
69.8k
  inflater->nv_name_keep = nv.name;
1806
69.8k
  inflater->nv_value_keep = nv.value;
1807
1808
69.8k
  inflater->namercbuf = NULL;
1809
69.8k
  inflater->valuercbuf = NULL;
1810
1811
69.8k
  return 0;
1812
69.8k
}
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
23.9k
                                     nghttp2_hd_nv *nv_out) {
1827
23.9k
  nghttp2_hd_nv nv;
1828
23.9k
  int rv;
1829
1830
23.9k
  nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1831
1832
23.9k
  if (inflater->no_index) {
1833
2.16k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1834
21.8k
  } else {
1835
21.8k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1836
21.8k
  }
1837
1838
23.9k
  nghttp2_rcbuf_incref(nv.name);
1839
1840
23.9k
  nv.value = inflater->valuercbuf;
1841
1842
23.9k
  if (inflater->index_required) {
1843
13.2k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1844
13.2k
    if (rv != 0) {
1845
0
      nghttp2_rcbuf_decref(nv.name);
1846
0
      return NGHTTP2_ERR_NOMEM;
1847
0
    }
1848
13.2k
  }
1849
1850
23.9k
  emit_header(nv_out, &nv);
1851
1852
23.9k
  inflater->nv_name_keep = nv.name;
1853
23.9k
  inflater->nv_value_keep = nv.value;
1854
1855
23.9k
  inflater->valuercbuf = NULL;
1856
1857
23.9k
  return 0;
1858
23.9k
}
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
0
                                     int in_final) {
1878
0
  nghttp2_ssize rv;
1879
0
  nghttp2_hd_nv hd_nv;
1880
1881
0
  rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
1882
0
                                in_final);
1883
1884
0
  if (rv < 0) {
1885
0
    return rv;
1886
0
  }
1887
1888
0
  if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
1889
0
    nv_out->name = hd_nv.name->base;
1890
0
    nv_out->namelen = hd_nv.name->len;
1891
1892
0
    nv_out->value = hd_nv.value->base;
1893
0
    nv_out->valuelen = hd_nv.value->len;
1894
1895
0
    nv_out->flags = hd_nv.flags;
1896
0
  }
1897
1898
0
  return rv;
1899
0
}
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
212k
                                       size_t inlen, int in_final) {
1905
212k
  nghttp2_ssize rv = 0;
1906
212k
  const uint8_t *first = in;
1907
212k
  const uint8_t *last = in + inlen;
1908
212k
  int rfin = 0;
1909
212k
  int busy = 0;
1910
212k
  nghttp2_mem *mem;
1911
1912
212k
  mem = inflater->ctx.mem;
1913
1914
212k
  if (inflater->ctx.bad) {
1915
0
    return NGHTTP2_ERR_HEADER_COMP;
1916
0
  }
1917
1918
212k
  DEBUGF("inflatehd: start state=%d\n", inflater->state);
1919
212k
  hd_inflate_keep_free(inflater);
1920
212k
  *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
1921
664k
  for (; in != last || busy;) {
1922
641k
    busy = 0;
1923
641k
    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
18.4k
    case NGHTTP2_HD_STATE_INFLATE_START:
1934
190k
    case NGHTTP2_HD_STATE_OPCODE:
1935
190k
      if ((*in & 0xe0u) == 0x20u) {
1936
3.01k
        DEBUGF("inflatehd: header table size change\n");
1937
3.01k
        if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
1938
40
          DEBUGF("inflatehd: header table size change must appear at the head "
1939
40
                 "of header block\n");
1940
40
          rv = NGHTTP2_ERR_HEADER_COMP;
1941
40
          goto fail;
1942
40
        }
1943
2.97k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1944
2.97k
        inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
1945
187k
      } else if (*in & 0x80u) {
1946
92.8k
        DEBUGF("inflatehd: indexed repr\n");
1947
92.8k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1948
92.8k
        inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1949
95.1k
      } else {
1950
95.1k
        if (*in == 0x40u || *in == 0 || *in == 0x10u) {
1951
70.4k
          DEBUGF("inflatehd: literal header repr - new name\n");
1952
70.4k
          inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
1953
70.4k
          inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
1954
70.4k
        } else {
1955
24.6k
          DEBUGF("inflatehd: literal header repr - indexed name\n");
1956
24.6k
          inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
1957
24.6k
          inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1958
24.6k
        }
1959
95.1k
        inflater->index_required = (*in & 0x40) != 0;
1960
95.1k
        inflater->no_index = (*in & 0xf0u) == 0x10u;
1961
95.1k
        DEBUGF("inflatehd: indexing required=%d, no_index=%d\n",
1962
95.1k
               inflater->index_required, inflater->no_index);
1963
95.1k
        if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1964
70.4k
          ++in;
1965
70.4k
        }
1966
95.1k
      }
1967
190k
      inflater->left = 0;
1968
190k
      inflater->shift = 0;
1969
190k
      break;
1970
3.39k
    case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
1971
3.39k
      rfin = 0;
1972
3.39k
      rv = hd_inflate_read_len(
1973
3.39k
        inflater, &rfin, in, last, 5,
1974
3.39k
        nghttp2_min_size(inflater->min_hd_table_bufsize_max,
1975
3.39k
                         inflater->settings_hd_table_bufsize_max));
1976
3.39k
      if (rv < 0) {
1977
209
        goto fail;
1978
209
      }
1979
3.18k
      in += rv;
1980
3.18k
      if (!rfin) {
1981
468
        goto almost_ok;
1982
468
      }
1983
2.71k
      DEBUGF("inflatehd: table_size=%zu\n", inflater->left);
1984
2.71k
      inflater->min_hd_table_bufsize_max = UINT32_MAX;
1985
2.71k
      inflater->ctx.hd_table_bufsize_max = inflater->left;
1986
2.71k
      hd_context_shrink_table_size(&inflater->ctx, NULL);
1987
2.71k
      inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
1988
2.71k
      break;
1989
117k
    case NGHTTP2_HD_STATE_READ_INDEX: {
1990
117k
      size_t prefixlen;
1991
1992
117k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
1993
92.8k
        prefixlen = 7;
1994
92.8k
      } else if (inflater->index_required) {
1995
13.5k
        prefixlen = 6;
1996
13.5k
      } else {
1997
11.2k
        prefixlen = 4;
1998
11.2k
      }
1999
2000
117k
      rfin = 0;
2001
117k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
2002
117k
                               get_max_index(&inflater->ctx));
2003
117k
      if (rv < 0) {
2004
377
        goto fail;
2005
377
      }
2006
2007
117k
      in += rv;
2008
2009
117k
      if (!rfin) {
2010
153
        goto almost_ok;
2011
153
      }
2012
2013
117k
      if (inflater->left == 0) {
2014
14
        rv = NGHTTP2_ERR_HEADER_COMP;
2015
14
        goto fail;
2016
14
      }
2017
2018
117k
      DEBUGF("inflatehd: index=%zu\n", inflater->left);
2019
117k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2020
92.6k
        inflater->index = inflater->left;
2021
92.6k
        --inflater->index;
2022
2023
92.6k
        hd_inflate_commit_indexed(inflater, nv_out);
2024
2025
92.6k
        inflater->state = NGHTTP2_HD_STATE_OPCODE;
2026
92.6k
        *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2027
92.6k
        return (nghttp2_ssize)(in - first);
2028
92.6k
      } else {
2029
24.4k
        inflater->index = inflater->left;
2030
24.4k
        --inflater->index;
2031
2032
24.4k
        inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2033
24.4k
      }
2034
24.4k
      break;
2035
117k
    }
2036
70.3k
    case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
2037
70.3k
      hd_inflate_set_huffman_encoded(inflater, in);
2038
70.3k
      inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
2039
70.3k
      inflater->left = 0;
2040
70.3k
      inflater->shift = 0;
2041
70.3k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2042
    /* Fall through */
2043
70.5k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
2044
70.5k
      rfin = 0;
2045
70.5k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2046
70.5k
      if (rv < 0) {
2047
179
        goto fail;
2048
179
      }
2049
70.3k
      in += rv;
2050
70.3k
      if (!rfin) {
2051
186
        DEBUGF("inflatehd: integer not fully decoded. current=%zu\n",
2052
186
               inflater->left);
2053
2054
186
        goto almost_ok;
2055
186
      }
2056
2057
70.1k
      if (inflater->huffman_encoded) {
2058
7.58k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2059
2060
7.58k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
2061
2062
7.58k
        rv =
2063
7.58k
          nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1, mem);
2064
62.5k
      } else {
2065
62.5k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
2066
62.5k
        rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
2067
62.5k
      }
2068
2069
70.1k
      if (rv != 0) {
2070
0
        goto fail;
2071
0
      }
2072
2073
70.1k
      nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
2074
70.1k
                            inflater->namercbuf->len);
2075
2076
70.1k
      break;
2077
7.57k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
2078
7.57k
      rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
2079
7.57k
      if (rv < 0) {
2080
17
        goto fail;
2081
17
      }
2082
2083
7.55k
      in += rv;
2084
2085
7.55k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2086
2087
7.55k
      if (inflater->left) {
2088
64
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2089
2090
64
        goto almost_ok;
2091
64
      }
2092
2093
7.48k
      *inflater->namebuf.last = '\0';
2094
7.48k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2095
2096
7.48k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2097
2098
7.48k
      break;
2099
62.5k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
2100
62.5k
      rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
2101
62.5k
      if (rv < 0) {
2102
0
        goto fail;
2103
0
      }
2104
2105
62.5k
      in += rv;
2106
2107
62.5k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2108
62.5k
      if (inflater->left) {
2109
92
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2110
2111
92
        goto almost_ok;
2112
92
      }
2113
2114
62.4k
      *inflater->namebuf.last = '\0';
2115
62.4k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2116
2117
62.4k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2118
2119
62.4k
      break;
2120
94.3k
    case NGHTTP2_HD_STATE_CHECK_VALUELEN:
2121
94.3k
      hd_inflate_set_huffman_encoded(inflater, in);
2122
94.3k
      inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
2123
94.3k
      inflater->left = 0;
2124
94.3k
      inflater->shift = 0;
2125
94.3k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2126
    /* Fall through */
2127
94.5k
    case NGHTTP2_HD_STATE_READ_VALUELEN:
2128
94.5k
      rfin = 0;
2129
94.5k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2130
94.5k
      if (rv < 0) {
2131
183
        goto fail;
2132
183
      }
2133
2134
94.3k
      in += rv;
2135
2136
94.3k
      if (!rfin) {
2137
218
        goto almost_ok;
2138
218
      }
2139
2140
94.1k
      DEBUGF("inflatehd: valuelen=%zu\n", inflater->left);
2141
2142
94.1k
      if (inflater->huffman_encoded) {
2143
12.8k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2144
2145
12.8k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
2146
2147
12.8k
        rv =
2148
12.8k
          nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1, mem);
2149
81.2k
      } else {
2150
81.2k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
2151
2152
81.2k
        rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
2153
81.2k
      }
2154
2155
94.1k
      if (rv != 0) {
2156
0
        goto fail;
2157
0
      }
2158
2159
94.1k
      nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
2160
94.1k
                            inflater->valuercbuf->len);
2161
2162
94.1k
      busy = 1;
2163
2164
94.1k
      break;
2165
12.8k
    case NGHTTP2_HD_STATE_READ_VALUEHUFF:
2166
12.8k
      rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
2167
12.8k
      if (rv < 0) {
2168
29
        goto fail;
2169
29
      }
2170
2171
12.8k
      in += rv;
2172
2173
12.8k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2174
2175
12.8k
      if (inflater->left) {
2176
104
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2177
2178
104
        goto almost_ok;
2179
104
      }
2180
2181
12.7k
      *inflater->valuebuf.last = '\0';
2182
12.7k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2183
2184
12.7k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2185
6.12k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2186
6.59k
      } else {
2187
6.59k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2188
6.59k
      }
2189
2190
12.7k
      if (rv != 0) {
2191
0
        goto fail;
2192
0
      }
2193
2194
12.7k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2195
12.7k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2196
2197
12.7k
      return (nghttp2_ssize)(in - first);
2198
81.3k
    case NGHTTP2_HD_STATE_READ_VALUE:
2199
81.3k
      rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
2200
81.3k
      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
81.3k
      in += rv;
2207
2208
81.3k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2209
2210
81.3k
      if (inflater->left) {
2211
181
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2212
181
        goto almost_ok;
2213
181
      }
2214
2215
81.1k
      *inflater->valuebuf.last = '\0';
2216
81.1k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2217
2218
81.1k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2219
63.7k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2220
63.7k
      } else {
2221
17.3k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2222
17.3k
      }
2223
2224
81.1k
      if (rv != 0) {
2225
0
        goto fail;
2226
0
      }
2227
2228
81.1k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2229
81.1k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2230
2231
81.1k
      return (nghttp2_ssize)(in - first);
2232
641k
    }
2233
641k
  }
2234
2235
212k
  assert(in == last);
2236
2237
23.4k
  DEBUGF("inflatehd: all input bytes were processed\n");
2238
2239
23.4k
  if (in_final) {
2240
16.7k
    DEBUGF("inflatehd: in_final set\n");
2241
2242
16.7k
    if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
2243
9.86k
        inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
2244
13
      DEBUGF("inflatehd: unacceptable state=%d\n", inflater->state);
2245
13
      rv = NGHTTP2_ERR_HEADER_COMP;
2246
2247
13
      goto fail;
2248
13
    }
2249
16.7k
    *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
2250
16.7k
  }
2251
23.4k
  return (nghttp2_ssize)(in - first);
2252
2253
1.46k
almost_ok:
2254
1.46k
  if (in_final) {
2255
27
    DEBUGF("inflatehd: input ended prematurely\n");
2256
2257
27
    rv = NGHTTP2_ERR_HEADER_COMP;
2258
2259
27
    goto fail;
2260
27
  }
2261
1.43k
  return (nghttp2_ssize)(in - first);
2262
2263
1.09k
fail:
2264
1.09k
  DEBUGF("inflatehd: error return %td\n", rv);
2265
2266
1.09k
  inflater->ctx.bad = 1;
2267
1.09k
  return rv;
2268
1.46k
}
2269
2270
16.7k
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
2271
16.7k
  hd_inflate_keep_free(inflater);
2272
16.7k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2273
16.7k
  return 0;
2274
16.7k
}
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
}