Coverage Report

Created: 2026-09-03 07:16

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
97.9k
static int memeq(const void *s1, const void *s2, size_t n) {
130
97.9k
  return memcmp(s1, s2, n) == 0;
131
97.9k
}
132
133
/*
134
 * This function was generated by genlibtokenlookup.py.  Inspired by
135
 * h2o header lookup.  https://github.com/h2o/h2o
136
 */
137
101k
static int32_t lookup_token(const uint8_t *name, size_t namelen) {
138
101k
  switch (namelen) {
139
2.20k
  case 2:
140
2.20k
    switch (name[1]) {
141
1.57k
    case 'e':
142
1.57k
      if (memeq("t", name, 1)) {
143
1.01k
        return NGHTTP2_TOKEN_TE;
144
1.01k
      }
145
560
      break;
146
2.20k
    }
147
1.18k
    break;
148
2.94k
  case 3:
149
2.94k
    switch (name[2]) {
150
1.09k
    case 'a':
151
1.09k
      if (memeq("vi", name, 2)) {
152
484
        return NGHTTP2_TOKEN_VIA;
153
484
      }
154
610
      break;
155
1.15k
    case 'e':
156
1.15k
      if (memeq("ag", name, 2)) {
157
518
        return NGHTTP2_TOKEN_AGE;
158
518
      }
159
639
      break;
160
2.94k
    }
161
1.94k
    break;
162
7.09k
  case 4:
163
7.09k
    switch (name[3]) {
164
906
    case 'e':
165
906
      if (memeq("dat", name, 3)) {
166
285
        return NGHTTP2_TOKEN_DATE;
167
285
      }
168
621
      break;
169
1.02k
    case 'g':
170
1.02k
      if (memeq("eta", name, 3)) {
171
417
        return NGHTTP2_TOKEN_ETAG;
172
417
      }
173
606
      break;
174
1.03k
    case 'k':
175
1.03k
      if (memeq("lin", name, 3)) {
176
410
        return NGHTTP2_TOKEN_LINK;
177
410
      }
178
621
      break;
179
1.15k
    case 'm':
180
1.15k
      if (memeq("fro", name, 3)) {
181
534
        return NGHTTP2_TOKEN_FROM;
182
534
      }
183
623
      break;
184
1.02k
    case 't':
185
1.02k
      if (memeq("hos", name, 3)) {
186
417
        return NGHTTP2_TOKEN_HOST;
187
417
      }
188
604
      break;
189
1.11k
    case 'y':
190
1.11k
      if (memeq("var", name, 3)) {
191
455
        return NGHTTP2_TOKEN_VARY;
192
455
      }
193
658
      break;
194
7.09k
    }
195
4.57k
    break;
196
4.57k
  case 5:
197
2.27k
    switch (name[4]) {
198
605
    case 'e':
199
605
      if (memeq("rang", name, 4)) {
200
279
        return NGHTTP2_TOKEN_RANGE;
201
279
      }
202
326
      break;
203
623
    case 'h':
204
623
      if (memeq(":pat", name, 4)) {
205
306
        return NGHTTP2_TOKEN__PATH;
206
306
      }
207
317
      break;
208
586
    case 'w':
209
586
      if (memeq("allo", name, 4)) {
210
278
        return NGHTTP2_TOKEN_ALLOW;
211
278
      }
212
308
      break;
213
2.27k
    }
214
1.41k
    break;
215
2.67k
  case 6:
216
2.67k
    switch (name[5]) {
217
646
    case 'e':
218
646
      if (memeq("cooki", name, 5)) {
219
340
        return NGHTTP2_TOKEN_COOKIE;
220
340
      }
221
306
      break;
222
584
    case 'r':
223
584
      if (memeq("serve", name, 5)) {
224
279
        return NGHTTP2_TOKEN_SERVER;
225
279
      }
226
305
      break;
227
955
    case 't':
228
955
      if (memeq("accep", name, 5)) {
229
279
        return NGHTTP2_TOKEN_ACCEPT;
230
279
      }
231
676
      if (memeq("expec", name, 5)) {
232
350
        return NGHTTP2_TOKEN_EXPECT;
233
350
      }
234
326
      break;
235
2.67k
    }
236
1.42k
    break;
237
4.06k
  case 7:
238
4.06k
    switch (name[6]) {
239
588
    case 'd':
240
588
      if (memeq(":metho", name, 6)) {
241
283
        return NGHTTP2_TOKEN__METHOD;
242
283
      }
243
305
      break;
244
906
    case 'e':
245
906
      if (memeq(":schem", name, 6)) {
246
283
        return NGHTTP2_TOKEN__SCHEME;
247
283
      }
248
623
      if (memeq("upgrad", name, 6)) {
249
290
        return NGHTTP2_TOKEN_UPGRADE;
250
290
      }
251
333
      break;
252
599
    case 'h':
253
599
      if (memeq("refres", name, 6)) {
254
287
        return NGHTTP2_TOKEN_REFRESH;
255
287
      }
256
312
      break;
257
594
    case 'r':
258
594
      if (memeq("refere", name, 6)) {
259
283
        return NGHTTP2_TOKEN_REFERER;
260
283
      }
261
311
      break;
262
1.03k
    case 's':
263
1.03k
      if (memeq(":statu", name, 6)) {
264
309
        return NGHTTP2_TOKEN__STATUS;
265
309
      }
266
729
      if (memeq("expire", name, 6)) {
267
284
        return NGHTTP2_TOKEN_EXPIRES;
268
284
      }
269
445
      break;
270
4.06k
    }
271
2.04k
    break;
272
4.86k
  case 8:
273
4.86k
    switch (name[7]) {
274
603
    case 'e':
275
603
      if (memeq("if-rang", name, 7)) {
276
278
        return NGHTTP2_TOKEN_IF_RANGE;
277
278
      }
278
325
      break;
279
582
    case 'h':
280
582
      if (memeq("if-matc", name, 7)) {
281
281
        return NGHTTP2_TOKEN_IF_MATCH;
282
281
      }
283
301
      break;
284
588
    case 'n':
285
588
      if (memeq("locatio", name, 7)) {
286
280
        return NGHTTP2_TOKEN_LOCATION;
287
280
      }
288
308
      break;
289
2.73k
    case 'y':
290
2.73k
      if (memeq("priorit", name, 7)) {
291
2.38k
        return NGHTTP2_TOKEN_PRIORITY;
292
2.38k
      }
293
346
      break;
294
4.86k
    }
295
1.64k
    break;
296
1.64k
  case 9:
297
1.07k
    switch (name[8]) {
298
679
    case 'l':
299
679
      if (memeq(":protoco", name, 8)) {
300
331
        return NGHTTP2_TOKEN__PROTOCOL;
301
331
      }
302
348
      break;
303
1.07k
    }
304
745
    break;
305
3.32k
  case 10:
306
3.32k
    switch (name[9]) {
307
972
    case 'e':
308
972
      if (memeq("keep-aliv", name, 9)) {
309
295
        return NGHTTP2_TOKEN_KEEP_ALIVE;
310
295
      }
311
677
      if (memeq("set-cooki", name, 9)) {
312
279
        return NGHTTP2_TOKEN_SET_COOKIE;
313
279
      }
314
398
      break;
315
723
    case 'n':
316
723
      if (memeq("connectio", name, 9)) {
317
289
        return NGHTTP2_TOKEN_CONNECTION;
318
289
      }
319
434
      break;
320
660
    case 't':
321
660
      if (memeq("user-agen", name, 9)) {
322
294
        return NGHTTP2_TOKEN_USER_AGENT;
323
294
      }
324
366
      break;
325
617
    case 'y':
326
617
      if (memeq(":authorit", name, 9)) {
327
280
        return NGHTTP2_TOKEN__AUTHORITY;
328
280
      }
329
337
      break;
330
3.32k
    }
331
1.88k
    break;
332
1.88k
  case 11:
333
1.01k
    switch (name[10]) {
334
644
    case 'r':
335
644
      if (memeq("retry-afte", name, 10)) {
336
279
        return NGHTTP2_TOKEN_RETRY_AFTER;
337
279
      }
338
365
      break;
339
1.01k
    }
340
734
    break;
341
1.58k
  case 12:
342
1.58k
    switch (name[11]) {
343
646
    case 'e':
344
646
      if (memeq("content-typ", name, 11)) {
345
280
        return NGHTTP2_TOKEN_CONTENT_TYPE;
346
280
      }
347
366
      break;
348
621
    case 's':
349
621
      if (memeq("max-forward", name, 11)) {
350
279
        return NGHTTP2_TOKEN_MAX_FORWARDS;
351
279
      }
352
342
      break;
353
1.58k
    }
354
1.03k
    break;
355
4.41k
  case 13:
356
4.41k
    switch (name[12]) {
357
766
    case 'd':
358
766
      if (memeq("last-modifie", name, 12)) {
359
337
        return NGHTTP2_TOKEN_LAST_MODIFIED;
360
337
      }
361
429
      break;
362
643
    case 'e':
363
643
      if (memeq("content-rang", name, 12)) {
364
278
        return NGHTTP2_TOKEN_CONTENT_RANGE;
365
278
      }
366
365
      break;
367
647
    case 'h':
368
647
      if (memeq("if-none-matc", name, 12)) {
369
278
        return NGHTTP2_TOKEN_IF_NONE_MATCH;
370
278
      }
371
369
      break;
372
652
    case 'l':
373
652
      if (memeq("cache-contro", name, 12)) {
374
284
        return NGHTTP2_TOKEN_CACHE_CONTROL;
375
284
      }
376
368
      break;
377
633
    case 'n':
378
633
      if (memeq("authorizatio", name, 12)) {
379
278
        return NGHTTP2_TOKEN_AUTHORIZATION;
380
278
      }
381
355
      break;
382
681
    case 's':
383
681
      if (memeq("accept-range", name, 12)) {
384
280
        return NGHTTP2_TOKEN_ACCEPT_RANGES;
385
280
      }
386
401
      break;
387
4.41k
    }
388
2.67k
    break;
389
2.67k
  case 14:
390
1.63k
    switch (name[13]) {
391
695
    case 'h':
392
695
      if (memeq("content-lengt", name, 13)) {
393
278
        return NGHTTP2_TOKEN_CONTENT_LENGTH;
394
278
      }
395
417
      break;
396
620
    case 't':
397
620
      if (memeq("accept-charse", name, 13)) {
398
278
        return NGHTTP2_TOKEN_ACCEPT_CHARSET;
399
278
      }
400
342
      break;
401
1.63k
    }
402
1.07k
    break;
403
1.81k
  case 15:
404
1.81k
    switch (name[14]) {
405
674
    case 'e':
406
674
      if (memeq("accept-languag", name, 14)) {
407
278
        return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
408
278
      }
409
396
      break;
410
717
    case 'g':
411
717
      if (memeq("accept-encodin", name, 14)) {
412
357
        return NGHTTP2_TOKEN_ACCEPT_ENCODING;
413
357
      }
414
360
      break;
415
1.81k
    }
416
1.18k
    break;
417
3.44k
  case 16:
418
3.44k
    switch (name[15]) {
419
1.17k
    case 'e':
420
1.17k
      if (memeq("content-languag", name, 15)) {
421
407
        return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
422
407
      }
423
766
      if (memeq("www-authenticat", name, 15)) {
424
299
        return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
425
299
      }
426
467
      break;
427
677
    case 'g':
428
677
      if (memeq("content-encodin", name, 15)) {
429
278
        return NGHTTP2_TOKEN_CONTENT_ENCODING;
430
278
      }
431
399
      break;
432
1.03k
    case 'n':
433
1.03k
      if (memeq("content-locatio", name, 15)) {
434
328
        return NGHTTP2_TOKEN_CONTENT_LOCATION;
435
328
      }
436
703
      if (memeq("proxy-connectio", name, 15)) {
437
284
        return NGHTTP2_TOKEN_PROXY_CONNECTION;
438
284
      }
439
419
      break;
440
3.44k
    }
441
1.84k
    break;
442
1.84k
  case 17:
443
1.71k
    switch (name[16]) {
444
693
    case 'e':
445
693
      if (memeq("if-modified-sinc", name, 16)) {
446
280
        return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
447
280
      }
448
413
      break;
449
674
    case 'g':
450
674
      if (memeq("transfer-encodin", name, 16)) {
451
322
        return NGHTTP2_TOKEN_TRANSFER_ENCODING;
452
322
      }
453
352
      break;
454
1.71k
    }
455
1.11k
    break;
456
1.11k
  case 18:
457
1.09k
    switch (name[17]) {
458
736
    case 'e':
459
736
      if (memeq("proxy-authenticat", name, 17)) {
460
312
        return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
461
312
      }
462
424
      break;
463
1.09k
    }
464
779
    break;
465
1.98k
  case 19:
466
1.98k
    switch (name[18]) {
467
650
    case 'e':
468
650
      if (memeq("if-unmodified-sinc", name, 18)) {
469
278
        return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
470
278
      }
471
372
      break;
472
991
    case 'n':
473
991
      if (memeq("content-dispositio", name, 18)) {
474
310
        return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
475
310
      }
476
681
      if (memeq("proxy-authorizatio", name, 18)) {
477
280
        return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
478
280
      }
479
401
      break;
480
1.98k
    }
481
1.11k
    break;
482
1.11k
  case 25:
483
983
    switch (name[24]) {
484
639
    case 'y':
485
639
      if (memeq("strict-transport-securit", name, 24)) {
486
278
        return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
487
278
      }
488
361
      break;
489
983
    }
490
705
    break;
491
1.29k
  case 27:
492
1.29k
    switch (name[26]) {
493
849
    case 'n':
494
849
      if (memeq("access-control-allow-origi", name, 26)) {
495
278
        return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
496
278
      }
497
571
      break;
498
1.29k
    }
499
1.01k
    break;
500
101k
  }
501
80.2k
  return -1;
502
101k
}
503
504
47.8k
void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
505
47.8k
  *ent = (nghttp2_hd_entry){
506
47.8k
    .nv = *nv,
507
47.8k
    .cnv =
508
47.8k
      {
509
47.8k
        .name = nv->name->base,
510
47.8k
        .value = nv->value->base,
511
47.8k
        .namelen = nv->name->len,
512
47.8k
        .valuelen = nv->value->len,
513
47.8k
        .flags = nv->flags,
514
47.8k
      },
515
47.8k
  };
516
517
47.8k
  nghttp2_rcbuf_incref(ent->nv.name);
518
47.8k
  nghttp2_rcbuf_incref(ent->nv.value);
519
47.8k
}
520
521
47.8k
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
522
47.8k
  nghttp2_rcbuf_decref(ent->nv.value);
523
47.8k
  nghttp2_rcbuf_decref(ent->nv.name);
524
47.8k
}
525
526
25.5k
static int name_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
527
25.5k
  return a->name->len == b->namelen &&
528
25.4k
         memeq(a->name->base, b->name, b->namelen);
529
25.5k
}
530
531
25.8k
static int value_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
532
25.8k
  return a->value->len == b->valuelen &&
533
24.9k
         memeq(a->value->base, b->value, b->valuelen);
534
25.8k
}
535
536
32.9k
static uint32_t name_hash(const nghttp2_nv *nv) {
537
  /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
538
32.9k
  uint32_t h = 2166136261u;
539
32.9k
  size_t i;
540
541
80.2k
  for (i = 0; i < nv->namelen; ++i) {
542
47.2k
    h ^= nv->name[i];
543
47.2k
    h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
544
47.2k
  }
545
546
32.9k
  return h;
547
32.9k
}
548
549
23.9k
static void hd_map_init(nghttp2_hd_map *map) { *map = (nghttp2_hd_map){0}; }
550
551
9.15k
static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
552
9.15k
  nghttp2_hd_entry **bucket;
553
554
9.15k
  bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
555
556
9.15k
  if (*bucket == NULL) {
557
8.24k
    *bucket = ent;
558
8.24k
    return;
559
8.24k
  }
560
561
  /* lower index is linked near the root */
562
911
  ent->next = *bucket;
563
911
  *bucket = ent;
564
911
}
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
34.5k
                                     uint32_t hash, int name_only) {
569
34.5k
  nghttp2_hd_entry *p;
570
34.5k
  nghttp2_hd_entry *res = NULL;
571
572
34.5k
  *exact_match = 0;
573
574
36.5k
  for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) {
575
26.3k
    if (token != p->nv.token ||
576
26.2k
        (token == -1 && (hash != p->hash || !name_eq(&p->nv, nv)))) {
577
493
      continue;
578
493
    }
579
25.8k
    if (!res) {
580
24.9k
      res = p;
581
24.9k
      if (name_only) {
582
19
        break;
583
19
      }
584
24.9k
    }
585
25.8k
    if (value_eq(&p->nv, nv)) {
586
24.2k
      res = p;
587
24.2k
      *exact_match = 1;
588
24.2k
      break;
589
24.2k
    }
590
25.8k
  }
591
592
34.5k
  return res;
593
34.5k
}
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
47.8k
                           nghttp2_mem *mem) {
613
47.8k
  size_t size;
614
47.8k
  const size_t max_size = SIZE_MAX / sizeof(nghttp2_hd_entry *);
615
616
47.8k
  if (bufsize > max_size) {
617
0
    return NGHTTP2_ERR_NOMEM;
618
0
  }
619
620
382k
  for (size = 1; size < bufsize; size <<= 1)
621
334k
    ;
622
623
47.8k
  if (size > max_size) {
624
0
    return NGHTTP2_ERR_NOMEM;
625
0
  }
626
627
47.8k
  ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
628
47.8k
  if (ringbuf->buffer == NULL) {
629
0
    return NGHTTP2_ERR_NOMEM;
630
0
  }
631
47.8k
  ringbuf->mask = size - 1;
632
47.8k
  ringbuf->first = 0;
633
47.8k
  ringbuf->len = 0;
634
47.8k
  return 0;
635
47.8k
}
636
637
static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
638
172k
                                        size_t idx) {
639
172k
  assert(idx < ringbuf->len);
640
172k
  return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
641
172k
}
642
643
static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
644
47.8k
                              nghttp2_mem *mem) {
645
47.8k
  size_t i;
646
47.8k
  size_t size;
647
47.8k
  nghttp2_hd_entry **buffer;
648
649
47.8k
  if (ringbuf->mask + 1 >= bufsize) {
650
47.8k
    return 0;
651
47.8k
  }
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
47.8k
static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
669
47.8k
  size_t i;
670
47.8k
  if (ringbuf == NULL) {
671
0
    return;
672
0
  }
673
86.3k
  for (i = 0; i < ringbuf->len; ++i) {
674
38.4k
    nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
675
676
38.4k
    nghttp2_hd_entry_free(ent);
677
38.4k
    nghttp2_mem_free(mem, ent);
678
38.4k
  }
679
47.8k
  nghttp2_mem_free(mem, ringbuf->buffer);
680
47.8k
}
681
682
static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
683
47.8k
                                 nghttp2_hd_entry *ent, nghttp2_mem *mem) {
684
47.8k
  int rv;
685
686
47.8k
  rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
687
688
47.8k
  if (rv != 0) {
689
0
    return rv;
690
0
  }
691
692
47.8k
  ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
693
47.8k
  ++ringbuf->len;
694
695
47.8k
  return 0;
696
47.8k
}
697
698
9.42k
static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
699
9.42k
  assert(ringbuf->len > 0);
700
9.42k
  --ringbuf->len;
701
9.42k
}
702
703
47.8k
static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
704
47.8k
  int rv;
705
47.8k
  context->mem = mem;
706
47.8k
  context->bad = 0;
707
47.8k
  context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
708
47.8k
  rv = hd_ringbuf_init(
709
47.8k
    &context->hd_table,
710
47.8k
    context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
711
47.8k
  if (rv != 0) {
712
0
    return rv;
713
0
  }
714
715
47.8k
  context->hd_table_bufsize = 0;
716
47.8k
  context->next_seq = 0;
717
718
47.8k
  return 0;
719
47.8k
}
720
721
47.8k
static void hd_context_free(nghttp2_hd_context *context) {
722
47.8k
  hd_ringbuf_free(&context->hd_table, context->mem);
723
47.8k
}
724
725
4.93k
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
726
4.93k
  return nghttp2_hd_deflate_init2(
727
4.93k
    deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
728
4.93k
}
729
730
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
731
                             size_t max_deflate_dynamic_table_size,
732
23.9k
                             nghttp2_mem *mem) {
733
23.9k
  int rv;
734
23.9k
  rv = hd_context_init(&deflater->ctx, mem);
735
23.9k
  if (rv != 0) {
736
0
    return rv;
737
0
  }
738
739
23.9k
  hd_map_init(&deflater->map);
740
741
23.9k
  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
23.9k
  } else {
745
23.9k
    deflater->notify_table_size_change = 0;
746
23.9k
  }
747
748
23.9k
  deflater->deflate_hd_table_bufsize_max = max_deflate_dynamic_table_size;
749
23.9k
  deflater->min_hd_table_bufsize_max = UINT32_MAX;
750
751
23.9k
  return 0;
752
23.9k
}
753
754
23.9k
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
755
23.9k
  int rv;
756
757
23.9k
  rv = hd_context_init(&inflater->ctx, mem);
758
23.9k
  if (rv != 0) {
759
0
    goto fail;
760
0
  }
761
762
23.9k
  inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
763
23.9k
  inflater->min_hd_table_bufsize_max = UINT32_MAX;
764
765
23.9k
  inflater->nv_name_keep = NULL;
766
23.9k
  inflater->nv_value_keep = NULL;
767
768
23.9k
  inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
769
23.9k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
770
771
23.9k
  nghttp2_buf_init(&inflater->namebuf);
772
23.9k
  nghttp2_buf_init(&inflater->valuebuf);
773
774
23.9k
  inflater->namercbuf = NULL;
775
23.9k
  inflater->valuercbuf = NULL;
776
777
23.9k
  inflater->huffman_encoded = 0;
778
23.9k
  inflater->index = 0;
779
23.9k
  inflater->left = 0;
780
23.9k
  inflater->shift = 0;
781
23.9k
  inflater->index_required = 0;
782
23.9k
  inflater->no_index = 0;
783
784
23.9k
  return 0;
785
786
0
fail:
787
0
  return rv;
788
23.9k
}
789
790
527k
static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
791
527k
  nghttp2_rcbuf_decref(inflater->nv_value_keep);
792
527k
  nghttp2_rcbuf_decref(inflater->nv_name_keep);
793
794
527k
  inflater->nv_value_keep = NULL;
795
527k
  inflater->nv_name_keep = NULL;
796
527k
}
797
798
23.9k
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
799
23.9k
  hd_context_free(&deflater->ctx);
800
23.9k
}
801
802
23.9k
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
803
23.9k
  hd_inflate_keep_free(inflater);
804
805
23.9k
  nghttp2_rcbuf_decref(inflater->valuercbuf);
806
23.9k
  nghttp2_rcbuf_decref(inflater->namercbuf);
807
808
23.9k
  hd_context_free(&inflater->ctx);
809
23.9k
}
810
811
92.4k
static size_t entry_room(size_t namelen, size_t valuelen) {
812
92.4k
  return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
813
92.4k
}
814
815
238k
static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
816
238k
  DEBUGF("inflatehd: header emission: %s: %s\n", nv->name->base,
817
238k
         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
238k
  *nv_out = *nv;
821
238k
}
822
823
43.7k
static size_t count_encoded_length(size_t n, size_t prefix) {
824
43.7k
  size_t k = (size_t)((1 << prefix) - 1);
825
43.7k
  size_t len = 0;
826
827
43.7k
  if (n < k) {
828
43.1k
    return 1;
829
43.1k
  }
830
831
642
  n -= k;
832
642
  ++len;
833
834
971
  for (; n >= 128; n >>= 7, ++len)
835
329
    ;
836
837
642
  return len + 1;
838
43.7k
}
839
840
43.7k
static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
841
43.7k
  size_t k = (size_t)((1 << prefix) - 1);
842
43.7k
  uint8_t *begin = buf;
843
844
43.7k
  *buf = (uint8_t)(*buf & ~k);
845
846
43.7k
  if (n < k) {
847
43.1k
    *buf = (uint8_t)(*buf | n);
848
43.1k
    return 1;
849
43.1k
  }
850
851
642
  *buf = (uint8_t)(*buf | k);
852
642
  ++buf;
853
854
642
  n -= k;
855
856
971
  for (; n >= 128; n >>= 7) {
857
329
    *buf++ = (uint8_t)((1 << 7) | (n & 0x7F));
858
329
  }
859
860
642
  *buf++ = (uint8_t)n;
861
862
642
  return (size_t)(buf - begin);
863
43.7k
}
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
346k
                                   size_t prefix) {
886
346k
  uint32_t k = (uint8_t)((1 << prefix) - 1);
887
346k
  uint32_t n = initial;
888
346k
  const uint8_t *start = in;
889
890
346k
  *shift_ptr = 0;
891
346k
  *fin = 0;
892
893
346k
  if (n == 0) {
894
344k
    if ((*in & k) != k) {
895
333k
      *res = (*in) & k;
896
333k
      *fin = 1;
897
333k
      return 1;
898
333k
    }
899
900
11.1k
    n = k;
901
902
11.1k
    if (++in == last) {
903
285
      *res = n;
904
285
      return (nghttp2_ssize)(in - start);
905
285
    }
906
11.1k
  }
907
908
34.3k
  for (; in != last; ++in, shift += 7) {
909
31.5k
    uint32_t add = *in & 0x7F;
910
911
31.5k
    if (shift >= 32) {
912
55
      DEBUGF("inflate: shift exponent overflow\n");
913
55
      return -1;
914
55
    }
915
916
31.5k
    if ((UINT32_MAX >> shift) < add) {
917
71
      DEBUGF("inflate: integer overflow on shift\n");
918
71
      return -1;
919
71
    }
920
921
31.4k
    add <<= shift;
922
923
31.4k
    if (UINT32_MAX - add < n) {
924
86
      DEBUGF("inflate: integer overflow on addition\n");
925
86
      return -1;
926
86
    }
927
928
31.3k
    n += add;
929
930
31.3k
    if ((*in & (1 << 7)) == 0) {
931
9.71k
      break;
932
9.71k
    }
933
31.3k
  }
934
935
12.4k
  *shift_ptr = shift;
936
937
12.4k
  if (in == last) {
938
2.72k
    *res = n;
939
2.72k
    return (nghttp2_ssize)(in - start);
940
2.72k
  }
941
942
9.71k
  *res = n;
943
9.71k
  *fin = 1;
944
9.71k
  return (nghttp2_ssize)(in + 1 - start);
945
12.4k
}
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
25.2k
static int emit_indexed_block(nghttp2_bufs *bufs, size_t idx) {
976
25.2k
  int rv;
977
25.2k
  size_t blocklen;
978
25.2k
  uint8_t sb[16];
979
25.2k
  uint8_t *bufp;
980
981
25.2k
  blocklen = count_encoded_length(idx + 1, 7);
982
983
25.2k
  DEBUGF("deflatehd: emit indexed index=%zu, %zu bytes\n", idx, blocklen);
984
985
25.2k
  if (sizeof(sb) < blocklen) {
986
0
    return NGHTTP2_ERR_HEADER_COMP;
987
0
  }
988
989
25.2k
  bufp = sb;
990
25.2k
  *bufp = 0x80U;
991
25.2k
  encode_length(bufp, idx + 1, 7);
992
993
25.2k
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
994
25.2k
  if (rv != 0) {
995
0
    return rv;
996
0
  }
997
998
25.2k
  return 0;
999
25.2k
}
1000
1001
17.6k
static int emit_string(nghttp2_bufs *bufs, const uint8_t *str, size_t len) {
1002
17.6k
  int rv;
1003
17.6k
  uint8_t sb[16];
1004
17.6k
  uint8_t *bufp;
1005
17.6k
  size_t blocklen;
1006
17.6k
  size_t enclen;
1007
17.6k
  int huffman = 0;
1008
1009
17.6k
  enclen = nghttp2_hd_huff_encode_count(str, len);
1010
1011
17.6k
  if (enclen < len) {
1012
1.29k
    huffman = 1;
1013
16.3k
  } else {
1014
16.3k
    enclen = len;
1015
16.3k
  }
1016
1017
17.6k
  blocklen = count_encoded_length(enclen, 7);
1018
1019
17.6k
  DEBUGF("deflatehd: emit string str=%.*s, length=%zu, huffman=%d, "
1020
17.6k
         "encoded_length=%zu\n",
1021
17.6k
         (int)len, (const char *)str, len, huffman, enclen);
1022
1023
17.6k
  if (sizeof(sb) < blocklen) {
1024
0
    return NGHTTP2_ERR_HEADER_COMP;
1025
0
  }
1026
1027
17.6k
  bufp = sb;
1028
17.6k
  *bufp = huffman ? 1 << 7 : 0;
1029
17.6k
  encode_length(bufp, enclen, 7);
1030
1031
17.6k
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1032
17.6k
  if (rv != 0) {
1033
0
    return rv;
1034
0
  }
1035
1036
17.6k
  if (huffman) {
1037
1.29k
    rv = nghttp2_hd_huff_encode(bufs, str, len);
1038
16.3k
  } else {
1039
16.3k
    assert(enclen == len);
1040
16.3k
    rv = nghttp2_bufs_add(bufs, str, len);
1041
16.3k
  }
1042
1043
17.6k
  return rv;
1044
17.6k
}
1045
1046
9.28k
static uint8_t pack_first_byte(int indexing_mode) {
1047
9.28k
  switch (indexing_mode) {
1048
9.15k
  case NGHTTP2_HD_WITH_INDEXING:
1049
9.15k
    return 0x40U;
1050
70
  case NGHTTP2_HD_WITHOUT_INDEXING:
1051
70
    return 0;
1052
63
  case NGHTTP2_HD_NEVER_INDEXING:
1053
63
    return 0x10U;
1054
0
  default:
1055
0
    assert(0);
1056
9.28k
  }
1057
  /* This is required to compile with android NDK r10d +
1058
     --enable-werror */
1059
0
  return 0;
1060
9.28k
}
1061
1062
static int emit_indname_block(nghttp2_bufs *bufs, size_t idx,
1063
943
                              const nghttp2_nv *nv, int indexing_mode) {
1064
943
  int rv;
1065
943
  uint8_t *bufp;
1066
943
  size_t blocklen;
1067
943
  uint8_t sb[16];
1068
943
  size_t prefixlen;
1069
1070
943
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1071
810
    prefixlen = 6;
1072
810
  } else {
1073
133
    prefixlen = 4;
1074
133
  }
1075
1076
943
  DEBUGF("deflatehd: emit indname index=%zu, valuelen=%zu, indexing_mode=%d\n",
1077
943
         idx, nv->valuelen, indexing_mode);
1078
1079
943
  blocklen = count_encoded_length(idx + 1, prefixlen);
1080
1081
943
  if (sizeof(sb) < blocklen) {
1082
0
    return NGHTTP2_ERR_HEADER_COMP;
1083
0
  }
1084
1085
943
  bufp = sb;
1086
1087
943
  *bufp = pack_first_byte(indexing_mode);
1088
1089
943
  encode_length(bufp, idx + 1, prefixlen);
1090
1091
943
  rv = nghttp2_bufs_add(bufs, sb, blocklen);
1092
943
  if (rv != 0) {
1093
0
    return rv;
1094
0
  }
1095
1096
943
  rv = emit_string(bufs, nv->value, nv->valuelen);
1097
943
  if (rv != 0) {
1098
0
    return rv;
1099
0
  }
1100
1101
943
  return 0;
1102
943
}
1103
1104
static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
1105
8.34k
                              int indexing_mode) {
1106
8.34k
  int rv;
1107
1108
8.34k
  DEBUGF(
1109
8.34k
    "deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
1110
8.34k
    nv->namelen, nv->valuelen, indexing_mode);
1111
1112
8.34k
  rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
1113
8.34k
  if (rv != 0) {
1114
0
    return rv;
1115
0
  }
1116
1117
8.34k
  rv = emit_string(bufs, nv->name, nv->namelen);
1118
8.34k
  if (rv != 0) {
1119
0
    return rv;
1120
0
  }
1121
1122
8.34k
  rv = emit_string(bufs, nv->value, nv->valuelen);
1123
8.34k
  if (rv != 0) {
1124
0
    return rv;
1125
0
  }
1126
1127
8.34k
  return 0;
1128
8.34k
}
1129
1130
static int add_hd_table_incremental(nghttp2_hd_context *context,
1131
                                    nghttp2_hd_nv *nv, nghttp2_hd_map *map,
1132
48.8k
                                    uint32_t hash) {
1133
48.8k
  int rv;
1134
48.8k
  nghttp2_hd_entry *new_ent;
1135
48.8k
  size_t room;
1136
48.8k
  nghttp2_mem *mem;
1137
1138
48.8k
  mem = context->mem;
1139
48.8k
  room = entry_room(nv->name->len, nv->value->len);
1140
1141
56.6k
  while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
1142
8.72k
         context->hd_table.len > 0) {
1143
7.78k
    size_t idx = context->hd_table.len - 1;
1144
7.78k
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1145
1146
7.78k
    context->hd_table_bufsize -=
1147
7.78k
      entry_room(ent->nv.name->len, ent->nv.value->len);
1148
1149
7.78k
    DEBUGF("hpack: remove item from header table: %s: %s\n",
1150
7.78k
           (char *)ent->nv.name->base, (char *)ent->nv.value->base);
1151
1152
7.78k
    hd_ringbuf_pop_back(&context->hd_table);
1153
7.78k
    if (map) {
1154
0
      hd_map_remove(map, ent);
1155
0
    }
1156
1157
7.78k
    nghttp2_hd_entry_free(ent);
1158
7.78k
    nghttp2_mem_free(mem, ent);
1159
7.78k
  }
1160
1161
48.8k
  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
937
    return 0;
1165
937
  }
1166
1167
47.8k
  new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
1168
47.8k
  if (new_ent == NULL) {
1169
0
    return NGHTTP2_ERR_NOMEM;
1170
0
  }
1171
1172
47.8k
  nghttp2_hd_entry_init(new_ent, nv);
1173
1174
47.8k
  rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
1175
1176
47.8k
  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
47.8k
  new_ent->seq = context->next_seq++;
1184
47.8k
  new_ent->hash = hash;
1185
1186
47.8k
  if (map) {
1187
9.15k
    hd_map_insert(map, new_ent);
1188
9.15k
  }
1189
1190
47.8k
  context->hd_table_bufsize += room;
1191
1192
47.8k
  return 0;
1193
47.8k
}
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
1.27k
                                         int name_only) {
1203
1.27k
  search_result res = {token, 0};
1204
1.27k
  int i;
1205
1.27k
  const nghttp2_hd_static_entry *ent;
1206
1207
1.27k
  if (name_only) {
1208
63
    return res;
1209
63
  }
1210
1211
1.21k
  for (i = token;
1212
1.73k
       i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token;
1213
1.48k
       ++i) {
1214
1.48k
    ent = &static_table[i];
1215
1.48k
    if (ent->value.len == nv->valuelen &&
1216
1.14k
        memcmp(ent->value.base, nv->value, nv->valuelen) == 0) {
1217
969
      res.index = i;
1218
969
      res.name_value_match = 1;
1219
969
      return res;
1220
969
    }
1221
1.48k
  }
1222
246
  return res;
1223
1.21k
}
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
34.5k
                                     uint32_t hash) {
1229
34.5k
  search_result res = {-1, 0};
1230
34.5k
  const nghttp2_hd_entry *ent;
1231
34.5k
  int exact_match;
1232
34.5k
  int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
1233
1234
34.5k
  exact_match = 0;
1235
34.5k
  ent = hd_map_find(map, &exact_match, nv, token, hash, name_only);
1236
1237
34.5k
  if (!exact_match && token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1238
1.27k
    return search_static_table(nv, token, name_only);
1239
1.27k
  }
1240
1241
33.2k
  if (ent == NULL) {
1242
8.34k
    return res;
1243
8.34k
  }
1244
1245
24.8k
  res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq +
1246
24.8k
                              NGHTTP2_STATIC_TABLE_LENGTH);
1247
24.8k
  res.name_value_match = exact_match;
1248
1249
24.8k
  return res;
1250
33.2k
}
1251
1252
static void hd_context_shrink_table_size(nghttp2_hd_context *context,
1253
8.80k
                                         nghttp2_hd_map *map) {
1254
8.80k
  nghttp2_mem *mem;
1255
1256
8.80k
  mem = context->mem;
1257
1258
10.4k
  while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
1259
1.64k
         context->hd_table.len > 0) {
1260
1.64k
    size_t idx = context->hd_table.len - 1;
1261
1.64k
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1262
1.64k
    context->hd_table_bufsize -=
1263
1.64k
      entry_room(ent->nv.name->len, ent->nv.value->len);
1264
1.64k
    hd_ringbuf_pop_back(&context->hd_table);
1265
1.64k
    if (map) {
1266
0
      hd_map_remove(map, ent);
1267
0
    }
1268
1269
1.64k
    nghttp2_hd_entry_free(ent);
1270
1.64k
    nghttp2_mem_free(mem, ent);
1271
1.64k
  }
1272
8.80k
}
1273
1274
int nghttp2_hd_deflate_change_table_size(
1275
2.92k
  nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
1276
2.92k
  size_t next_bufsize = nghttp2_min_size(
1277
2.92k
    settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
1278
1279
2.92k
  deflater->ctx.hd_table_bufsize_max = next_bufsize;
1280
1281
2.92k
  deflater->min_hd_table_bufsize_max =
1282
2.92k
    nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
1283
1284
2.92k
  deflater->notify_table_size_change = 1;
1285
1286
2.92k
  hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
1287
2.92k
  return 0;
1288
2.92k
}
1289
1290
int nghttp2_hd_inflate_change_table_size(
1291
147
  nghttp2_hd_inflater *inflater, size_t settings_max_dynamic_table_size) {
1292
147
  switch (inflater->state) {
1293
27
  case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1294
147
  case NGHTTP2_HD_STATE_INFLATE_START:
1295
147
    break;
1296
0
  default:
1297
0
    return NGHTTP2_ERR_INVALID_STATE;
1298
147
  }
1299
1300
147
  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
147
  if (inflater->ctx.hd_table_bufsize_max > settings_max_dynamic_table_size) {
1310
118
    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
118
    inflater->min_hd_table_bufsize_max = settings_max_dynamic_table_size;
1314
1315
118
    inflater->ctx.hd_table_bufsize_max = settings_max_dynamic_table_size;
1316
1317
118
    hd_context_shrink_table_size(&inflater->ctx, NULL);
1318
118
  }
1319
1320
147
  return 0;
1321
147
}
1322
1323
#define INDEX_RANGE_VALID(context, idx)                                        \
1324
0
  ((idx) < (context)->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH)
1325
1326
173k
static size_t get_max_index(nghttp2_hd_context *context) {
1327
173k
  return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
1328
173k
}
1329
1330
172k
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
1331
172k
  assert(INDEX_RANGE_VALID(context, idx));
1332
172k
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1333
124k
    return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
1334
124k
      ->nv;
1335
124k
  } else {
1336
47.4k
    const nghttp2_hd_static_entry *ent = &static_table[idx];
1337
47.4k
    return (nghttp2_hd_nv){
1338
47.4k
      .name = (nghttp2_rcbuf *)&ent->name,
1339
47.4k
      .value = (nghttp2_rcbuf *)&ent->value,
1340
47.4k
      .token = ent->token,
1341
47.4k
      .flags = NGHTTP2_NV_FLAG_NONE,
1342
47.4k
    };
1343
47.4k
  }
1344
172k
}
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
34.4k
                                      const nghttp2_nv *nv, int32_t token) {
1360
34.4k
  if (token == NGHTTP2_TOKEN__PATH || token == NGHTTP2_TOKEN_AGE ||
1361
34.2k
      token == NGHTTP2_TOKEN_CONTENT_LENGTH || token == NGHTTP2_TOKEN_ETAG ||
1362
34.2k
      token == NGHTTP2_TOKEN_IF_MODIFIED_SINCE ||
1363
34.2k
      token == NGHTTP2_TOKEN_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION ||
1364
34.1k
      token == NGHTTP2_TOKEN_SET_COOKIE ||
1365
34.1k
      entry_room(nv->namelen, nv->valuelen) >
1366
34.1k
        deflater->ctx.hd_table_bufsize_max * 3 / 4) {
1367
287
    return NGHTTP2_HD_WITHOUT_INDEXING;
1368
287
  }
1369
1370
34.1k
  return NGHTTP2_HD_WITH_INDEXING;
1371
34.4k
}
1372
1373
static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
1374
34.5k
                      const nghttp2_nv *nv) {
1375
34.5k
  int rv;
1376
34.5k
  search_result res;
1377
34.5k
  nghttp2_ssize idx;
1378
34.5k
  int indexing_mode;
1379
34.5k
  int32_t token;
1380
34.5k
  nghttp2_mem *mem;
1381
34.5k
  uint32_t hash = 0;
1382
1383
34.5k
  DEBUGF("deflatehd: deflating %.*s: %.*s\n", (int)nv->namelen, nv->name,
1384
34.5k
         (int)nv->valuelen, nv->value);
1385
1386
34.5k
  mem = deflater->ctx.mem;
1387
1388
34.5k
  token = lookup_token(nv->name, nv->namelen);
1389
34.5k
  if (token == -1) {
1390
32.9k
    hash = name_hash(nv);
1391
32.9k
  } else if (token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1392
1.33k
    hash = static_table[token].hash;
1393
1.33k
  }
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
34.5k
  indexing_mode = token == NGHTTP2_TOKEN_AUTHORIZATION ||
1400
34.4k
                      (token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
1401
34.4k
                      (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
1402
34.5k
                    ? NGHTTP2_HD_NEVER_INDEXING
1403
34.5k
                    : hd_deflate_decide_indexing(deflater, nv, token);
1404
1405
34.5k
  res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
1406
34.5k
                        &deflater->map, hash);
1407
1408
34.5k
  idx = res.index;
1409
1410
34.5k
  if (res.name_value_match) {
1411
25.2k
    DEBUGF("deflatehd: name/value match index=%td\n", idx);
1412
1413
25.2k
    rv = emit_indexed_block(bufs, (size_t)idx);
1414
25.2k
    if (rv != 0) {
1415
0
      return rv;
1416
0
    }
1417
1418
25.2k
    return 0;
1419
25.2k
  }
1420
1421
9.28k
  if (res.index != -1) {
1422
943
    DEBUGF("deflatehd: name match index=%td\n", res.index);
1423
943
  }
1424
1425
9.28k
  if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
1426
9.15k
    nghttp2_hd_nv hd_nv;
1427
1428
9.15k
    if (idx != -1) {
1429
810
      hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
1430
810
      nghttp2_rcbuf_incref(hd_nv.name);
1431
8.34k
    } else {
1432
8.34k
      rv = nghttp2_rcbuf_new2(&hd_nv.name, nv->name, nv->namelen, mem);
1433
8.34k
      if (rv != 0) {
1434
0
        return rv;
1435
0
      }
1436
8.34k
    }
1437
1438
9.15k
    rv = nghttp2_rcbuf_new2(&hd_nv.value, nv->value, nv->valuelen, mem);
1439
1440
9.15k
    if (rv != 0) {
1441
0
      nghttp2_rcbuf_decref(hd_nv.name);
1442
0
      return rv;
1443
0
    }
1444
1445
9.15k
    hd_nv.token = token;
1446
9.15k
    hd_nv.flags = NGHTTP2_NV_FLAG_NONE;
1447
1448
9.15k
    rv = add_hd_table_incremental(&deflater->ctx, &hd_nv, &deflater->map, hash);
1449
1450
9.15k
    nghttp2_rcbuf_decref(hd_nv.value);
1451
9.15k
    nghttp2_rcbuf_decref(hd_nv.name);
1452
1453
9.15k
    if (rv != 0) {
1454
0
      return NGHTTP2_ERR_HEADER_COMP;
1455
0
    }
1456
9.15k
  }
1457
9.28k
  if (idx == -1) {
1458
8.34k
    rv = emit_newname_block(bufs, nv, indexing_mode);
1459
8.34k
  } else {
1460
943
    rv = emit_indname_block(bufs, (size_t)idx, nv, indexing_mode);
1461
943
  }
1462
9.28k
  if (rv != 0) {
1463
0
    return rv;
1464
0
  }
1465
1466
9.28k
  return 0;
1467
9.28k
}
1468
1469
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
1470
                               nghttp2_bufs *bufs, const nghttp2_nv *nv,
1471
4.93k
                               size_t nvlen) {
1472
4.93k
  size_t i;
1473
4.93k
  int rv = 0;
1474
1475
4.93k
  if (deflater->ctx.bad) {
1476
0
    return NGHTTP2_ERR_HEADER_COMP;
1477
0
  }
1478
1479
4.93k
  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
39.4k
  for (i = 0; i < nvlen; ++i) {
1503
34.5k
    rv = deflate_nv(deflater, bufs, &nv[i]);
1504
34.5k
    if (rv != 0) {
1505
0
      goto fail;
1506
0
    }
1507
34.5k
  }
1508
1509
4.93k
  DEBUGF("deflatehd: all input name/value pairs were deflated\n");
1510
1511
4.93k
  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
4.93k
}
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
165k
                                           const uint8_t *in) {
1670
165k
  inflater->huffman_encoded = (*in & (1 << 7)) != 0;
1671
165k
}
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
346k
                                         size_t maxlen) {
1690
346k
  nghttp2_ssize rv;
1691
346k
  uint32_t out;
1692
1693
346k
  *rfin = 0;
1694
1695
346k
  rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
1696
346k
                     inflater->shift, in, last, prefix);
1697
1698
346k
  if (rv == -1) {
1699
212
    DEBUGF("inflatehd: integer decoding failed\n");
1700
212
    return NGHTTP2_ERR_HEADER_COMP;
1701
212
  }
1702
1703
346k
  if (out > maxlen) {
1704
1.87k
    DEBUGF("inflatehd: integer exceeded the maximum value %zu\n", maxlen);
1705
1.87k
    return NGHTTP2_ERR_HEADER_COMP;
1706
1.87k
  }
1707
1708
344k
  inflater->left = out;
1709
1710
344k
  DEBUGF("inflatehd: decoded integer is %u\n", out);
1711
1712
344k
  return rv;
1713
346k
}
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
31.2k
                                          const uint8_t *last) {
1731
31.2k
  nghttp2_ssize readlen;
1732
31.2k
  int fin = 0;
1733
31.2k
  if ((size_t)(last - in) >= inflater->left) {
1734
30.8k
    last = in + inflater->left;
1735
30.8k
    fin = 1;
1736
30.8k
  }
1737
31.2k
  readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
1738
31.2k
                                   (size_t)(last - in), fin);
1739
1740
31.2k
  if (readlen < 0) {
1741
24
    DEBUGF("inflatehd: huffman decoding failed\n");
1742
24
    return readlen;
1743
24
  }
1744
31.2k
  if (nghttp2_hd_huff_decode_failure_state(&inflater->huff_decode_ctx)) {
1745
25
    DEBUGF("inflatehd: huffman decoding failed\n");
1746
25
    return NGHTTP2_ERR_HEADER_COMP;
1747
25
  }
1748
1749
31.1k
  inflater->left -= (size_t)readlen;
1750
31.1k
  return readlen;
1751
31.2k
}
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
133k
                                     const uint8_t *last) {
1768
133k
  size_t len = nghttp2_min_size((size_t)(last - in), inflater->left);
1769
1770
133k
  buf->last = nghttp2_cpymem(buf->last, in, len);
1771
1772
133k
  inflater->left -= len;
1773
133k
  return (nghttp2_ssize)len;
1774
133k
}
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
142k
                                      nghttp2_hd_nv *nv_out) {
1782
142k
  nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1783
1784
142k
  emit_header(nv_out, &nv);
1785
142k
}
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
67.0k
                                     nghttp2_hd_nv *nv_out) {
1800
67.0k
  nghttp2_hd_nv nv;
1801
67.0k
  int rv;
1802
1803
67.0k
  if (inflater->no_index) {
1804
2.99k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1805
64.1k
  } else {
1806
64.1k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1807
64.1k
  }
1808
1809
67.0k
  nv.name = inflater->namercbuf;
1810
67.0k
  nv.value = inflater->valuercbuf;
1811
67.0k
  nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
1812
1813
67.0k
  if (inflater->index_required) {
1814
16.8k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1815
1816
16.8k
    if (rv != 0) {
1817
0
      return rv;
1818
0
    }
1819
16.8k
  }
1820
1821
67.0k
  emit_header(nv_out, &nv);
1822
1823
67.0k
  inflater->nv_name_keep = nv.name;
1824
67.0k
  inflater->nv_value_keep = nv.value;
1825
1826
67.0k
  inflater->namercbuf = NULL;
1827
67.0k
  inflater->valuercbuf = NULL;
1828
1829
67.0k
  return 0;
1830
67.0k
}
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
28.9k
                                     nghttp2_hd_nv *nv_out) {
1845
28.9k
  nghttp2_hd_nv nv;
1846
28.9k
  int rv;
1847
1848
28.9k
  nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1849
1850
28.9k
  if (inflater->no_index) {
1851
1.16k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1852
27.7k
  } else {
1853
27.7k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1854
27.7k
  }
1855
1856
28.9k
  nghttp2_rcbuf_incref(nv.name);
1857
1858
28.9k
  nv.value = inflater->valuercbuf;
1859
1860
28.9k
  if (inflater->index_required) {
1861
22.8k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1862
22.8k
    if (rv != 0) {
1863
0
      nghttp2_rcbuf_decref(nv.name);
1864
0
      return NGHTTP2_ERR_NOMEM;
1865
0
    }
1866
22.8k
  }
1867
1868
28.9k
  emit_header(nv_out, &nv);
1869
1870
28.9k
  inflater->nv_name_keep = nv.name;
1871
28.9k
  inflater->nv_value_keep = nv.value;
1872
1873
28.9k
  inflater->valuercbuf = NULL;
1874
1875
28.9k
  return 0;
1876
28.9k
}
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
19.7k
                                     int in_final) {
1896
19.7k
  nghttp2_ssize rv;
1897
19.7k
  nghttp2_hd_nv hd_nv;
1898
1899
19.7k
  rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
1900
19.7k
                                in_final);
1901
1902
19.7k
  if (rv < 0) {
1903
0
    return rv;
1904
0
  }
1905
1906
19.7k
  if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
1907
17.2k
    *nv_out = (nghttp2_nv){
1908
17.2k
      .name = hd_nv.name->base,
1909
17.2k
      .value = hd_nv.value->base,
1910
17.2k
      .namelen = hd_nv.name->len,
1911
17.2k
      .valuelen = hd_nv.value->len,
1912
17.2k
      .flags = hd_nv.flags,
1913
17.2k
    };
1914
17.2k
  }
1915
1916
19.7k
  return rv;
1917
19.7k
}
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
377k
                                       size_t inlen, int in_final) {
1923
377k
  nghttp2_ssize rv = 0;
1924
377k
  const uint8_t *first = in;
1925
377k
  const uint8_t *last = in + inlen;
1926
377k
  int rfin = 0;
1927
377k
  int busy = 0;
1928
377k
  nghttp2_mem *mem;
1929
1930
377k
  mem = inflater->ctx.mem;
1931
1932
377k
  if (inflater->ctx.bad) {
1933
0
    return NGHTTP2_ERR_HEADER_COMP;
1934
0
  }
1935
1936
377k
  DEBUGF("inflatehd: start state=%d\n", inflater->state);
1937
377k
  hd_inflate_keep_free(inflater);
1938
377k
  *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
1939
892k
  for (; in != last || busy;) {
1940
759k
    busy = 0;
1941
759k
    switch (inflater->state) {
1942
17
    case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1943
17
      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
117k
    case NGHTTP2_HD_STATE_INFLATE_START:
1952
248k
    case NGHTTP2_HD_STATE_OPCODE:
1953
248k
      if ((*in & 0xE0U) == 0x20U) {
1954
6.35k
        DEBUGF("inflatehd: header table size change\n");
1955
6.35k
        if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
1956
31
          DEBUGF("inflatehd: header table size change must appear at the head "
1957
31
                 "of header block\n");
1958
31
          rv = NGHTTP2_ERR_HEADER_COMP;
1959
31
          goto fail;
1960
31
        }
1961
6.32k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1962
6.32k
        inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
1963
241k
      } else if (*in & 0x80U) {
1964
143k
        DEBUGF("inflatehd: indexed repr\n");
1965
143k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1966
143k
        inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1967
143k
      } else {
1968
98.6k
        if (*in == 0x40U || *in == 0 || *in == 0x10U) {
1969
68.3k
          DEBUGF("inflatehd: literal header repr - new name\n");
1970
68.3k
          inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
1971
68.3k
          inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
1972
68.3k
        } else {
1973
30.3k
          DEBUGF("inflatehd: literal header repr - indexed name\n");
1974
30.3k
          inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
1975
30.3k
          inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1976
30.3k
        }
1977
98.6k
        inflater->index_required = (*in & 0x40) != 0;
1978
98.6k
        inflater->no_index = (*in & 0xF0U) == 0x10U;
1979
98.6k
        DEBUGF("inflatehd: indexing required=%d, no_index=%d\n",
1980
98.6k
               inflater->index_required, inflater->no_index);
1981
98.6k
        if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1982
68.3k
          ++in;
1983
68.3k
        }
1984
98.6k
      }
1985
248k
      inflater->left = 0;
1986
248k
      inflater->shift = 0;
1987
248k
      break;
1988
7.01k
    case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
1989
7.01k
      rfin = 0;
1990
7.01k
      rv = hd_inflate_read_len(
1991
7.01k
        inflater, &rfin, in, last, 5,
1992
7.01k
        nghttp2_min_size(inflater->min_hd_table_bufsize_max,
1993
7.01k
                         inflater->settings_hd_table_bufsize_max));
1994
7.01k
      if (rv < 0) {
1995
451
        goto fail;
1996
451
      }
1997
6.56k
      in += rv;
1998
6.56k
      if (!rfin) {
1999
802
        goto almost_ok;
2000
802
      }
2001
5.76k
      DEBUGF("inflatehd: table_size=%zu\n", inflater->left);
2002
5.76k
      inflater->min_hd_table_bufsize_max = UINT32_MAX;
2003
5.76k
      inflater->ctx.hd_table_bufsize_max = inflater->left;
2004
5.76k
      hd_context_shrink_table_size(&inflater->ctx, NULL);
2005
5.76k
      inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2006
5.76k
      break;
2007
173k
    case NGHTTP2_HD_STATE_READ_INDEX: {
2008
173k
      size_t prefixlen;
2009
2010
173k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2011
143k
        prefixlen = 7;
2012
143k
      } else if (inflater->index_required) {
2013
23.4k
        prefixlen = 6;
2014
23.4k
      } else {
2015
7.32k
        prefixlen = 4;
2016
7.32k
      }
2017
2018
173k
      rfin = 0;
2019
173k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
2020
173k
                               get_max_index(&inflater->ctx));
2021
173k
      if (rv < 0) {
2022
782
        goto fail;
2023
782
      }
2024
2025
173k
      in += rv;
2026
2027
173k
      if (!rfin) {
2028
488
        goto almost_ok;
2029
488
      }
2030
2031
172k
      if (inflater->left == 0) {
2032
29
        rv = NGHTTP2_ERR_HEADER_COMP;
2033
29
        goto fail;
2034
29
      }
2035
2036
172k
      DEBUGF("inflatehd: index=%zu\n", inflater->left);
2037
172k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2038
142k
        inflater->index = inflater->left;
2039
142k
        --inflater->index;
2040
2041
142k
        hd_inflate_commit_indexed(inflater, nv_out);
2042
2043
142k
        inflater->state = NGHTTP2_HD_STATE_OPCODE;
2044
142k
        *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2045
142k
        return (nghttp2_ssize)(in - first);
2046
142k
      } else {
2047
29.9k
        inflater->index = inflater->left;
2048
29.9k
        --inflater->index;
2049
2050
29.9k
        inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2051
29.9k
      }
2052
29.9k
      break;
2053
172k
    }
2054
68.2k
    case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
2055
68.2k
      hd_inflate_set_huffman_encoded(inflater, in);
2056
68.2k
      inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
2057
68.2k
      inflater->left = 0;
2058
68.2k
      inflater->shift = 0;
2059
68.2k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2060
    /* Fall through */
2061
68.5k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
2062
68.5k
      rfin = 0;
2063
68.5k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2064
68.5k
      if (rv < 0) {
2065
423
        goto fail;
2066
423
      }
2067
68.1k
      in += rv;
2068
68.1k
      if (!rfin) {
2069
425
        DEBUGF("inflatehd: integer not fully decoded. current=%zu\n",
2070
425
               inflater->left);
2071
2072
425
        goto almost_ok;
2073
425
      }
2074
2075
67.6k
      if (inflater->huffman_encoded) {
2076
16.2k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2077
2078
16.2k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
2079
2080
16.2k
        rv = nghttp2_rcbuf_new(
2081
16.2k
          &inflater->namercbuf,
2082
16.2k
          nghttp2_huff_estimate_decode_length(inflater->left) + 1, mem);
2083
51.4k
      } else {
2084
51.4k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
2085
51.4k
        rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
2086
51.4k
      }
2087
2088
67.6k
      if (rv != 0) {
2089
0
        goto fail;
2090
0
      }
2091
2092
67.6k
      nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
2093
67.6k
                            inflater->namercbuf->len);
2094
2095
67.6k
      break;
2096
16.1k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
2097
16.1k
      rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
2098
16.1k
      if (rv < 0) {
2099
25
        goto fail;
2100
25
      }
2101
2102
16.1k
      in += rv;
2103
2104
16.1k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2105
2106
16.1k
      if (inflater->left) {
2107
123
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2108
2109
123
        goto almost_ok;
2110
123
      }
2111
2112
16.0k
      *inflater->namebuf.last = '\0';
2113
16.0k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2114
2115
16.0k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2116
2117
16.0k
      break;
2118
51.3k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
2119
51.3k
      rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
2120
51.3k
      if (rv < 0) {
2121
0
        goto fail;
2122
0
      }
2123
2124
51.3k
      in += rv;
2125
2126
51.3k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2127
51.3k
      if (inflater->left) {
2128
147
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2129
2130
147
        goto almost_ok;
2131
147
      }
2132
2133
51.2k
      *inflater->namebuf.last = '\0';
2134
51.2k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2135
2136
51.2k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2137
2138
51.2k
      break;
2139
96.9k
    case NGHTTP2_HD_STATE_CHECK_VALUELEN:
2140
96.9k
      hd_inflate_set_huffman_encoded(inflater, in);
2141
96.9k
      inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
2142
96.9k
      inflater->left = 0;
2143
96.9k
      inflater->shift = 0;
2144
96.9k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2145
    /* Fall through */
2146
97.3k
    case NGHTTP2_HD_STATE_READ_VALUELEN:
2147
97.3k
      rfin = 0;
2148
97.3k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2149
97.3k
      if (rv < 0) {
2150
428
        goto fail;
2151
428
      }
2152
2153
96.9k
      in += rv;
2154
2155
96.9k
      if (!rfin) {
2156
447
        goto almost_ok;
2157
447
      }
2158
2159
96.4k
      DEBUGF("inflatehd: valuelen=%zu\n", inflater->left);
2160
2161
96.4k
      if (inflater->huffman_encoded) {
2162
15.0k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2163
2164
15.0k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
2165
2166
15.0k
        rv = nghttp2_rcbuf_new(
2167
15.0k
          &inflater->valuercbuf,
2168
15.0k
          nghttp2_huff_estimate_decode_length(inflater->left) + 1, mem);
2169
81.4k
      } else {
2170
81.4k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
2171
2172
81.4k
        rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
2173
81.4k
      }
2174
2175
96.4k
      if (rv != 0) {
2176
0
        goto fail;
2177
0
      }
2178
2179
96.4k
      nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
2180
96.4k
                            inflater->valuercbuf->len);
2181
2182
96.4k
      busy = 1;
2183
2184
96.4k
      break;
2185
15.0k
    case NGHTTP2_HD_STATE_READ_VALUEHUFF:
2186
15.0k
      rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
2187
15.0k
      if (rv < 0) {
2188
24
        goto fail;
2189
24
      }
2190
2191
15.0k
      in += rv;
2192
2193
15.0k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2194
2195
15.0k
      if (inflater->left) {
2196
184
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2197
2198
184
        goto almost_ok;
2199
184
      }
2200
2201
14.8k
      *inflater->valuebuf.last = '\0';
2202
14.8k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2203
2204
14.8k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2205
4.97k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2206
9.88k
      } else {
2207
9.88k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2208
9.88k
      }
2209
2210
14.8k
      if (rv != 0) {
2211
0
        goto fail;
2212
0
      }
2213
2214
14.8k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2215
14.8k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2216
2217
14.8k
      return (nghttp2_ssize)(in - first);
2218
81.7k
    case NGHTTP2_HD_STATE_READ_VALUE:
2219
81.7k
      rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
2220
81.7k
      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
81.7k
      in += rv;
2227
2228
81.7k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2229
2230
81.7k
      if (inflater->left) {
2231
519
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2232
519
        goto almost_ok;
2233
519
      }
2234
2235
81.1k
      *inflater->valuebuf.last = '\0';
2236
81.1k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2237
2238
81.1k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2239
62.1k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2240
62.1k
      } else {
2241
19.0k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2242
19.0k
      }
2243
2244
81.1k
      if (rv != 0) {
2245
0
        goto fail;
2246
0
      }
2247
2248
81.1k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2249
81.1k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2250
2251
81.1k
      return (nghttp2_ssize)(in - first);
2252
759k
    }
2253
759k
  }
2254
2255
377k
  assert(in == last);
2256
2257
133k
  DEBUGF("inflatehd: all input bytes were processed\n");
2258
2259
133k
  if (in_final) {
2260
126k
    DEBUGF("inflatehd: in_final set\n");
2261
2262
126k
    if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
2263
25.2k
        inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
2264
47
      DEBUGF("inflatehd: unacceptable state=%d\n", inflater->state);
2265
47
      rv = NGHTTP2_ERR_HEADER_COMP;
2266
2267
47
      goto fail;
2268
47
    }
2269
126k
    *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
2270
126k
  }
2271
133k
  return (nghttp2_ssize)(in - first);
2272
2273
3.13k
almost_ok:
2274
3.13k
  if (in_final) {
2275
30
    DEBUGF("inflatehd: input ended prematurely\n");
2276
2277
30
    rv = NGHTTP2_ERR_HEADER_COMP;
2278
2279
30
    goto fail;
2280
30
  }
2281
3.10k
  return (nghttp2_ssize)(in - first);
2282
2283
2.27k
fail:
2284
2.27k
  DEBUGF("inflatehd: error return %td\n", rv);
2285
2286
2.27k
  inflater->ctx.bad = 1;
2287
2.27k
  return rv;
2288
3.13k
}
2289
2290
126k
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
2291
126k
  hd_inflate_keep_free(inflater);
2292
126k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2293
126k
  return 0;
2294
126k
}
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
}