Coverage Report

Created: 2026-06-10 06:19

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