Coverage Report

Created: 2026-10-17 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nghttp2/lib/nghttp2_hd.c
Line
Count
Source
1
/*
2
 * nghttp2 - HTTP/2 C Library
3
 *
4
 * Copyright (c) 2013 Tatsuhiro Tsujikawa
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining
7
 * a copy of this software and associated documentation files (the
8
 * "Software"), to deal in the Software without restriction, including
9
 * without limitation the rights to use, copy, modify, merge, publish,
10
 * distribute, sublicense, and/or sell copies of the Software, and to
11
 * permit persons to whom the Software is furnished to do so, subject to
12
 * the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be
15
 * included in all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
 */
25
#include "nghttp2_hd.h"
26
27
#include <string.h>
28
#include <assert.h>
29
#include <stdio.h>
30
31
#include "nghttp2_helper.h"
32
#include "nghttp2_int.h"
33
#include "nghttp2_debug.h"
34
35
/* Make scalar initialization form of nghttp2_hd_entry */
36
#define MAKE_STATIC_ENT(N, V, T, H)                                            \
37
  {                                                                            \
38
    .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
27.7k
static int memeq(const void *s1, const void *s2, size_t n) {
130
27.7k
  return memcmp(s1, s2, n) == 0;
131
27.7k
}
132
133
/*
134
 * This function was generated by genlibtokenlookup.py.  Inspired by
135
 * h2o header lookup.  https://github.com/h2o/h2o
136
 */
137
41.0k
static int32_t lookup_token(const uint8_t *name, size_t namelen) {
138
41.0k
  switch (namelen) {
139
756
  case 2:
140
756
    switch (name[1]) {
141
544
    case 'e':
142
544
      if (memeq("t", name, 1)) {
143
332
        return NGHTTP2_TOKEN_TE;
144
332
      }
145
212
      break;
146
756
    }
147
424
    break;
148
1.07k
  case 3:
149
1.07k
    switch (name[2]) {
150
420
    case 'a':
151
420
      if (memeq("vi", name, 2)) {
152
194
        return NGHTTP2_TOKEN_VIA;
153
194
      }
154
226
      break;
155
411
    case 'e':
156
411
      if (memeq("ag", name, 2)) {
157
194
        return NGHTTP2_TOKEN_AGE;
158
194
      }
159
217
      break;
160
1.07k
    }
161
690
    break;
162
3.22k
  case 4:
163
3.22k
    switch (name[3]) {
164
438
    case 'e':
165
438
      if (memeq("dat", name, 3)) {
166
198
        return NGHTTP2_TOKEN_DATE;
167
198
      }
168
240
      break;
169
431
    case 'g':
170
431
      if (memeq("eta", name, 3)) {
171
194
        return NGHTTP2_TOKEN_ETAG;
172
194
      }
173
237
      break;
174
438
    case 'k':
175
438
      if (memeq("lin", name, 3)) {
176
199
        return NGHTTP2_TOKEN_LINK;
177
199
      }
178
239
      break;
179
504
    case 'm':
180
504
      if (memeq("fro", name, 3)) {
181
194
        return NGHTTP2_TOKEN_FROM;
182
194
      }
183
310
      break;
184
428
    case 't':
185
428
      if (memeq("hos", name, 3)) {
186
194
        return NGHTTP2_TOKEN_HOST;
187
194
      }
188
234
      break;
189
447
    case 'y':
190
447
      if (memeq("var", name, 3)) {
191
200
        return NGHTTP2_TOKEN_VARY;
192
200
      }
193
247
      break;
194
3.22k
    }
195
2.05k
    break;
196
2.05k
  case 5:
197
1.37k
    switch (name[4]) {
198
389
    case 'e':
199
389
      if (memeq("rang", name, 4)) {
200
194
        return NGHTTP2_TOKEN_RANGE;
201
194
      }
202
195
      break;
203
389
    case 'h':
204
389
      if (memeq(":pat", name, 4)) {
205
194
        return NGHTTP2_TOKEN__PATH;
206
194
      }
207
195
      break;
208
394
    case 'w':
209
394
      if (memeq("allo", name, 4)) {
210
195
        return NGHTTP2_TOKEN_ALLOW;
211
195
      }
212
199
      break;
213
1.37k
    }
214
787
    break;
215
1.88k
  case 6:
216
1.88k
    switch (name[5]) {
217
396
    case 'e':
218
396
      if (memeq("cooki", name, 5)) {
219
194
        return NGHTTP2_TOKEN_COOKIE;
220
194
      }
221
202
      break;
222
389
    case 'r':
223
389
      if (memeq("serve", name, 5)) {
224
194
        return NGHTTP2_TOKEN_SERVER;
225
194
      }
226
195
      break;
227
873
    case 't':
228
873
      if (memeq("accep", name, 5)) {
229
194
        return NGHTTP2_TOKEN_ACCEPT;
230
194
      }
231
679
      if (memeq("expec", name, 5)) {
232
454
        return NGHTTP2_TOKEN_EXPECT;
233
454
      }
234
225
      break;
235
1.88k
    }
236
847
    break;
237
2.71k
  case 7:
238
2.71k
    switch (name[6]) {
239
403
    case 'd':
240
403
      if (memeq(":metho", name, 6)) {
241
208
        return NGHTTP2_TOKEN__METHOD;
242
208
      }
243
195
      break;
244
682
    case 'e':
245
682
      if (memeq(":schem", name, 6)) {
246
194
        return NGHTTP2_TOKEN__SCHEME;
247
194
      }
248
488
      if (memeq("upgrad", name, 6)) {
249
280
        return NGHTTP2_TOKEN_UPGRADE;
250
280
      }
251
208
      break;
252
440
    case 'h':
253
440
      if (memeq("refres", name, 6)) {
254
242
        return NGHTTP2_TOKEN_REFRESH;
255
242
      }
256
198
      break;
257
389
    case 'r':
258
389
      if (memeq("refere", name, 6)) {
259
194
        return NGHTTP2_TOKEN_REFERER;
260
194
      }
261
195
      break;
262
593
    case 's':
263
593
      if (memeq(":statu", name, 6)) {
264
194
        return NGHTTP2_TOKEN__STATUS;
265
194
      }
266
399
      if (memeq("expire", name, 6)) {
267
194
        return NGHTTP2_TOKEN_EXPIRES;
268
194
      }
269
205
      break;
270
2.71k
    }
271
1.20k
    break;
272
2.82k
  case 8:
273
2.82k
    switch (name[7]) {
274
412
    case 'e':
275
412
      if (memeq("if-rang", name, 7)) {
276
194
        return NGHTTP2_TOKEN_IF_RANGE;
277
194
      }
278
218
      break;
279
392
    case 'h':
280
392
      if (memeq("if-matc", name, 7)) {
281
194
        return NGHTTP2_TOKEN_IF_MATCH;
282
194
      }
283
198
      break;
284
391
    case 'n':
285
391
      if (memeq("locatio", name, 7)) {
286
195
        return NGHTTP2_TOKEN_LOCATION;
287
195
      }
288
196
      break;
289
1.42k
    case 'y':
290
1.42k
      if (memeq("priorit", name, 7)) {
291
1.22k
        return NGHTTP2_TOKEN_PRIORITY;
292
1.22k
      }
293
202
      break;
294
2.82k
    }
295
1.02k
    break;
296
1.02k
  case 9:
297
644
    switch (name[8]) {
298
426
    case 'l':
299
426
      if (memeq(":protoco", name, 8)) {
300
232
        return NGHTTP2_TOKEN__PROTOCOL;
301
232
      }
302
194
      break;
303
644
    }
304
412
    break;
305
2.12k
  case 10:
306
2.12k
    switch (name[9]) {
307
668
    case 'e':
308
668
      if (memeq("keep-aliv", name, 9)) {
309
251
        return NGHTTP2_TOKEN_KEEP_ALIVE;
310
251
      }
311
417
      if (memeq("set-cooki", name, 9)) {
312
194
        return NGHTTP2_TOKEN_SET_COOKIE;
313
194
      }
314
223
      break;
315
413
    case 'n':
316
413
      if (memeq("connectio", name, 9)) {
317
200
        return NGHTTP2_TOKEN_CONNECTION;
318
200
      }
319
213
      break;
320
395
    case 't':
321
395
      if (memeq("user-agen", name, 9)) {
322
194
        return NGHTTP2_TOKEN_USER_AGENT;
323
194
      }
324
201
      break;
325
402
    case 'y':
326
402
      if (memeq(":authorit", name, 9)) {
327
194
        return NGHTTP2_TOKEN__AUTHORITY;
328
194
      }
329
208
      break;
330
2.12k
    }
331
1.08k
    break;
332
1.08k
  case 11:
333
608
    switch (name[10]) {
334
402
    case 'r':
335
402
      if (memeq("retry-afte", name, 10)) {
336
195
        return NGHTTP2_TOKEN_RETRY_AFTER;
337
195
      }
338
207
      break;
339
608
    }
340
413
    break;
341
989
  case 12:
342
989
    switch (name[11]) {
343
395
    case 'e':
344
395
      if (memeq("content-typ", name, 11)) {
345
194
        return NGHTTP2_TOKEN_CONTENT_TYPE;
346
194
      }
347
201
      break;
348
398
    case 's':
349
398
      if (memeq("max-forward", name, 11)) {
350
194
        return NGHTTP2_TOKEN_MAX_FORWARDS;
351
194
      }
352
204
      break;
353
989
    }
354
601
    break;
355
2.67k
  case 13:
356
2.67k
    switch (name[12]) {
357
421
    case 'd':
358
421
      if (memeq("last-modifie", name, 12)) {
359
194
        return NGHTTP2_TOKEN_LAST_MODIFIED;
360
194
      }
361
227
      break;
362
406
    case 'e':
363
406
      if (memeq("content-rang", name, 12)) {
364
194
        return NGHTTP2_TOKEN_CONTENT_RANGE;
365
194
      }
366
212
      break;
367
407
    case 'h':
368
407
      if (memeq("if-none-matc", name, 12)) {
369
201
        return NGHTTP2_TOKEN_IF_NONE_MATCH;
370
201
      }
371
206
      break;
372
399
    case 'l':
373
399
      if (memeq("cache-contro", name, 12)) {
374
194
        return NGHTTP2_TOKEN_CACHE_CONTROL;
375
194
      }
376
205
      break;
377
406
    case 'n':
378
406
      if (memeq("authorizatio", name, 12)) {
379
194
        return NGHTTP2_TOKEN_AUTHORIZATION;
380
194
      }
381
212
      break;
382
405
    case 's':
383
405
      if (memeq("accept-range", name, 12)) {
384
194
        return NGHTTP2_TOKEN_ACCEPT_RANGES;
385
194
      }
386
211
      break;
387
2.67k
    }
388
1.50k
    break;
389
1.50k
  case 14:
390
1.09k
    switch (name[13]) {
391
402
    case 'h':
392
402
      if (memeq("content-lengt", name, 13)) {
393
194
        return NGHTTP2_TOKEN_CONTENT_LENGTH;
394
194
      }
395
208
      break;
396
449
    case 't':
397
449
      if (memeq("accept-charse", name, 13)) {
398
243
        return NGHTTP2_TOKEN_ACCEPT_CHARSET;
399
243
      }
400
206
      break;
401
1.09k
    }
402
658
    break;
403
1.17k
  case 15:
404
1.17k
    switch (name[14]) {
405
399
    case 'e':
406
399
      if (memeq("accept-languag", name, 14)) {
407
194
        return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
408
194
      }
409
205
      break;
410
548
    case 'g':
411
548
      if (memeq("accept-encodin", name, 14)) {
412
213
        return NGHTTP2_TOKEN_ACCEPT_ENCODING;
413
213
      }
414
335
      break;
415
1.17k
    }
416
765
    break;
417
1.92k
  case 16:
418
1.92k
    switch (name[15]) {
419
666
    case 'e':
420
666
      if (memeq("content-languag", name, 15)) {
421
242
        return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
422
242
      }
423
424
      if (memeq("www-authenticat", name, 15)) {
424
195
        return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
425
195
      }
426
229
      break;
427
405
    case 'g':
428
405
      if (memeq("content-encodin", name, 15)) {
429
194
        return NGHTTP2_TOKEN_CONTENT_ENCODING;
430
194
      }
431
211
      break;
432
648
    case 'n':
433
648
      if (memeq("content-locatio", name, 15)) {
434
231
        return NGHTTP2_TOKEN_CONTENT_LOCATION;
435
231
      }
436
417
      if (memeq("proxy-connectio", name, 15)) {
437
203
        return NGHTTP2_TOKEN_PROXY_CONNECTION;
438
203
      }
439
214
      break;
440
1.92k
    }
441
861
    break;
442
1.00k
  case 17:
443
1.00k
    switch (name[16]) {
444
408
    case 'e':
445
408
      if (memeq("if-modified-sinc", name, 16)) {
446
194
        return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
447
194
      }
448
214
      break;
449
401
    case 'g':
450
401
      if (memeq("transfer-encodin", name, 16)) {
451
205
        return NGHTTP2_TOKEN_TRANSFER_ENCODING;
452
205
      }
453
196
      break;
454
1.00k
    }
455
610
    break;
456
610
  case 18:
457
603
    switch (name[17]) {
458
395
    case 'e':
459
395
      if (memeq("proxy-authenticat", name, 17)) {
460
194
        return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
461
194
      }
462
201
      break;
463
603
    }
464
409
    break;
465
1.23k
  case 19:
466
1.23k
    switch (name[18]) {
467
414
    case 'e':
468
414
      if (memeq("if-unmodified-sinc", name, 18)) {
469
201
        return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
470
201
      }
471
213
      break;
472
606
    case 'n':
473
606
      if (memeq("content-dispositio", name, 18)) {
474
194
        return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
475
194
      }
476
412
      if (memeq("proxy-authorizatio", name, 18)) {
477
194
        return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
478
194
      }
479
218
      break;
480
1.23k
    }
481
641
    break;
482
641
  case 25:
483
620
    switch (name[24]) {
484
419
    case 'y':
485
419
      if (memeq("strict-transport-securit", name, 24)) {
486
210
        return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
487
210
      }
488
209
      break;
489
620
    }
490
410
    break;
491
610
  case 27:
492
610
    switch (name[26]) {
493
400
    case 'n':
494
400
      if (memeq("access-control-allow-origi", name, 26)) {
495
195
        return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
496
195
      }
497
205
      break;
498
610
    }
499
415
    break;
500
41.0k
  }
501
27.7k
  return -1;
502
41.0k
}
503
504
15.2k
void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
505
15.2k
  *ent = (nghttp2_hd_entry){
506
15.2k
    .nv = *nv,
507
15.2k
    .cnv =
508
15.2k
      {
509
15.2k
        .name = nv->name->base,
510
15.2k
        .value = nv->value->base,
511
15.2k
        .namelen = nv->name->len,
512
15.2k
        .valuelen = nv->value->len,
513
15.2k
        .flags = nv->flags,
514
15.2k
      },
515
15.2k
  };
516
517
15.2k
  nghttp2_rcbuf_incref(ent->nv.name);
518
15.2k
  nghttp2_rcbuf_incref(ent->nv.value);
519
15.2k
}
520
521
15.2k
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
522
15.2k
  nghttp2_rcbuf_decref(ent->nv.value);
523
15.2k
  nghttp2_rcbuf_decref(ent->nv.name);
524
15.2k
}
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
9.54k
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
19.0k
                           nghttp2_mem *mem) {
613
19.0k
  size_t size;
614
19.0k
  const size_t max_size = SIZE_MAX / sizeof(nghttp2_hd_entry *);
615
616
19.0k
  if (bufsize > max_size) {
617
0
    return NGHTTP2_ERR_NOMEM;
618
0
  }
619
620
152k
  for (size = 1; size < bufsize; size <<= 1)
621
133k
    ;
622
623
19.0k
  if (size > max_size) {
624
0
    return NGHTTP2_ERR_NOMEM;
625
0
  }
626
627
19.0k
  ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
628
19.0k
  if (ringbuf->buffer == NULL) {
629
0
    return NGHTTP2_ERR_NOMEM;
630
0
  }
631
19.0k
  ringbuf->mask = size - 1;
632
19.0k
  ringbuf->first = 0;
633
19.0k
  ringbuf->len = 0;
634
19.0k
  return 0;
635
19.0k
}
636
637
static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
638
89.8k
                                        size_t idx) {
639
89.8k
  assert(idx < ringbuf->len);
640
89.8k
  return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
641
89.8k
}
642
643
static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
644
15.2k
                              nghttp2_mem *mem) {
645
15.2k
  size_t i;
646
15.2k
  size_t size;
647
15.2k
  nghttp2_hd_entry **buffer;
648
649
15.2k
  if (ringbuf->mask + 1 >= bufsize) {
650
15.2k
    return 0;
651
15.2k
  }
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
19.0k
static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
669
19.0k
  size_t i;
670
19.0k
  if (ringbuf == NULL) {
671
0
    return;
672
0
  }
673
30.2k
  for (i = 0; i < ringbuf->len; ++i) {
674
11.1k
    nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
675
676
11.1k
    nghttp2_hd_entry_free(ent);
677
11.1k
    nghttp2_mem_free(mem, ent);
678
11.1k
  }
679
19.0k
  nghttp2_mem_free(mem, ringbuf->buffer);
680
19.0k
}
681
682
static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
683
15.2k
                                 nghttp2_hd_entry *ent, nghttp2_mem *mem) {
684
15.2k
  int rv;
685
686
15.2k
  rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
687
688
15.2k
  if (rv != 0) {
689
0
    return rv;
690
0
  }
691
692
15.2k
  ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
693
15.2k
  ++ringbuf->len;
694
695
15.2k
  return 0;
696
15.2k
}
697
698
4.10k
static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
699
4.10k
  assert(ringbuf->len > 0);
700
4.10k
  --ringbuf->len;
701
4.10k
}
702
703
19.0k
static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
704
19.0k
  int rv;
705
19.0k
  context->mem = mem;
706
19.0k
  context->bad = 0;
707
19.0k
  context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
708
19.0k
  rv = hd_ringbuf_init(
709
19.0k
    &context->hd_table,
710
19.0k
    context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
711
19.0k
  if (rv != 0) {
712
0
    return rv;
713
0
  }
714
715
19.0k
  context->hd_table_bufsize = 0;
716
19.0k
  context->next_seq = 0;
717
718
19.0k
  return 0;
719
19.0k
}
720
721
19.0k
static void hd_context_free(nghttp2_hd_context *context) {
722
19.0k
  hd_ringbuf_free(&context->hd_table, context->mem);
723
19.0k
}
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
9.54k
                             nghttp2_mem *mem) {
733
9.54k
  int rv;
734
9.54k
  rv = hd_context_init(&deflater->ctx, mem);
735
9.54k
  if (rv != 0) {
736
0
    return rv;
737
0
  }
738
739
9.54k
  hd_map_init(&deflater->map);
740
741
9.54k
  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
9.54k
  } else {
745
9.54k
    deflater->notify_table_size_change = 0;
746
9.54k
  }
747
748
9.54k
  deflater->deflate_hd_table_bufsize_max = max_deflate_dynamic_table_size;
749
9.54k
  deflater->min_hd_table_bufsize_max = UINT32_MAX;
750
751
9.54k
  return 0;
752
9.54k
}
753
754
9.54k
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
755
9.54k
  int rv;
756
757
9.54k
  rv = hd_context_init(&inflater->ctx, mem);
758
9.54k
  if (rv != 0) {
759
0
    goto fail;
760
0
  }
761
762
9.54k
  inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
763
9.54k
  inflater->min_hd_table_bufsize_max = UINT32_MAX;
764
765
9.54k
  inflater->nv_name_keep = NULL;
766
9.54k
  inflater->nv_value_keep = NULL;
767
768
9.54k
  inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
769
9.54k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
770
771
9.54k
  nghttp2_buf_init(&inflater->namebuf);
772
9.54k
  nghttp2_buf_init(&inflater->valuebuf);
773
774
9.54k
  inflater->namercbuf = NULL;
775
9.54k
  inflater->valuercbuf = NULL;
776
777
9.54k
  inflater->huffman_encoded = 0;
778
9.54k
  inflater->index = 0;
779
9.54k
  inflater->left = 0;
780
9.54k
  inflater->shift = 0;
781
9.54k
  inflater->index_required = 0;
782
9.54k
  inflater->no_index = 0;
783
784
9.54k
  return 0;
785
786
0
fail:
787
0
  return rv;
788
9.54k
}
789
790
304k
static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
791
304k
  nghttp2_rcbuf_decref(inflater->nv_value_keep);
792
304k
  nghttp2_rcbuf_decref(inflater->nv_name_keep);
793
794
304k
  inflater->nv_value_keep = NULL;
795
304k
  inflater->nv_name_keep = NULL;
796
304k
}
797
798
9.54k
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
799
9.54k
  hd_context_free(&deflater->ctx);
800
9.54k
}
801
802
9.54k
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
803
9.54k
  hd_inflate_keep_free(inflater);
804
805
9.54k
  nghttp2_rcbuf_decref(inflater->valuercbuf);
806
9.54k
  nghttp2_rcbuf_decref(inflater->namercbuf);
807
808
9.54k
  hd_context_free(&inflater->ctx);
809
9.54k
}
810
811
19.8k
static size_t entry_room(size_t namelen, size_t valuelen) {
812
19.8k
  return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
813
19.8k
}
814
815
134k
static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
816
134k
  DEBUGF("inflatehd: header emission: %s: %s\n", nv->name->base,
817
134k
         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
134k
  *nv_out = *nv;
821
134k
}
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
197k
                                   size_t prefix) {
886
197k
  uint32_t k = (uint8_t)((1 << prefix) - 1);
887
197k
  uint32_t n = initial;
888
197k
  const uint8_t *start = in;
889
890
197k
  *shift_ptr = 0;
891
197k
  *fin = 0;
892
893
197k
  if (n == 0) {
894
195k
    if ((*in & k) != k) {
895
188k
      *res = (*in) & k;
896
188k
      *fin = 1;
897
188k
      return 1;
898
188k
    }
899
900
7.28k
    n = k;
901
902
7.28k
    if (++in == last) {
903
426
      *res = n;
904
426
      return (nghttp2_ssize)(in - start);
905
426
    }
906
7.28k
  }
907
908
21.6k
  for (; in != last; ++in, shift += 7) {
909
19.8k
    uint32_t add = *in & 0x7F;
910
911
19.8k
    if (shift >= 32) {
912
27
      DEBUGF("inflate: shift exponent overflow\n");
913
27
      return -1;
914
27
    }
915
916
19.8k
    if ((UINT32_MAX >> shift) < add) {
917
30
      DEBUGF("inflate: integer overflow on shift\n");
918
30
      return -1;
919
30
    }
920
921
19.8k
    add <<= shift;
922
923
19.8k
    if (UINT32_MAX - add < n) {
924
43
      DEBUGF("inflate: integer overflow on addition\n");
925
43
      return -1;
926
43
    }
927
928
19.7k
    n += add;
929
930
19.7k
    if ((*in & (1 << 7)) == 0) {
931
6.65k
      break;
932
6.65k
    }
933
19.7k
  }
934
935
8.41k
  *shift_ptr = shift;
936
937
8.41k
  if (in == last) {
938
1.76k
    *res = n;
939
1.76k
    return (nghttp2_ssize)(in - start);
940
1.76k
  }
941
942
6.65k
  *res = n;
943
6.65k
  *fin = 1;
944
6.65k
  return (nghttp2_ssize)(in + 1 - start);
945
8.41k
}
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
15.7k
                                    uint32_t hash) {
1133
15.7k
  int rv;
1134
15.7k
  nghttp2_hd_entry *new_ent;
1135
15.7k
  size_t room;
1136
15.7k
  nghttp2_mem *mem;
1137
1138
15.7k
  mem = context->mem;
1139
15.7k
  room = entry_room(nv->name->len, nv->value->len);
1140
1141
18.9k
  while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
1142
3.70k
         context->hd_table.len > 0) {
1143
3.19k
    size_t idx = context->hd_table.len - 1;
1144
3.19k
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1145
1146
3.19k
    context->hd_table_bufsize -=
1147
3.19k
      entry_room(ent->nv.name->len, ent->nv.value->len);
1148
1149
3.19k
    DEBUGF("hpack: remove item from header table: %s: %s\n",
1150
3.19k
           (char *)ent->nv.name->base, (char *)ent->nv.value->base);
1151
1152
3.19k
    hd_ringbuf_pop_back(&context->hd_table);
1153
3.19k
    if (map) {
1154
0
      hd_map_remove(map, ent);
1155
0
    }
1156
1157
3.19k
    nghttp2_hd_entry_free(ent);
1158
3.19k
    nghttp2_mem_free(mem, ent);
1159
3.19k
  }
1160
1161
15.7k
  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
508
    return 0;
1165
508
  }
1166
1167
15.2k
  new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
1168
15.2k
  if (new_ent == NULL) {
1169
0
    return NGHTTP2_ERR_NOMEM;
1170
0
  }
1171
1172
15.2k
  nghttp2_hd_entry_init(new_ent, nv);
1173
1174
15.2k
  rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
1175
1176
15.2k
  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
15.2k
  new_ent->seq = context->next_seq++;
1184
15.2k
  new_ent->hash = hash;
1185
1186
15.2k
  if (map) {
1187
0
    hd_map_insert(map, new_ent);
1188
0
  }
1189
1190
15.2k
  context->hd_table_bufsize += room;
1191
1192
15.2k
  return 0;
1193
15.2k
}
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
7.83k
                                         nghttp2_hd_map *map) {
1254
7.83k
  nghttp2_mem *mem;
1255
1256
7.83k
  mem = context->mem;
1257
1258
8.74k
  while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
1259
912
         context->hd_table.len > 0) {
1260
912
    size_t idx = context->hd_table.len - 1;
1261
912
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1262
912
    context->hd_table_bufsize -=
1263
912
      entry_room(ent->nv.name->len, ent->nv.value->len);
1264
912
    hd_ringbuf_pop_back(&context->hd_table);
1265
912
    if (map) {
1266
0
      hd_map_remove(map, ent);
1267
0
    }
1268
1269
912
    nghttp2_hd_entry_free(ent);
1270
912
    nghttp2_mem_free(mem, ent);
1271
912
  }
1272
7.83k
}
1273
1274
int nghttp2_hd_deflate_change_table_size(
1275
2.04k
  nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
1276
2.04k
  size_t next_bufsize = nghttp2_min_size(
1277
2.04k
    settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
1278
1279
2.04k
  deflater->ctx.hd_table_bufsize_max = next_bufsize;
1280
1281
2.04k
  deflater->min_hd_table_bufsize_max =
1282
2.04k
    nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
1283
1284
2.04k
  deflater->notify_table_size_change = 1;
1285
1286
2.04k
  hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
1287
2.04k
  return 0;
1288
2.04k
}
1289
1290
int nghttp2_hd_inflate_change_table_size(
1291
127
  nghttp2_hd_inflater *inflater, size_t settings_max_dynamic_table_size) {
1292
127
  switch (inflater->state) {
1293
25
  case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1294
127
  case NGHTTP2_HD_STATE_INFLATE_START:
1295
127
    break;
1296
0
  default:
1297
0
    return NGHTTP2_ERR_INVALID_STATE;
1298
127
  }
1299
1300
127
  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
127
  if (inflater->ctx.hd_table_bufsize_max > settings_max_dynamic_table_size) {
1310
100
    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
100
    inflater->min_hd_table_bufsize_max = settings_max_dynamic_table_size;
1314
1315
100
    inflater->ctx.hd_table_bufsize_max = settings_max_dynamic_table_size;
1316
1317
100
    hd_context_shrink_table_size(&inflater->ctx, NULL);
1318
100
  }
1319
1320
127
  return 0;
1321
127
}
1322
1323
#define INDEX_RANGE_VALID(context, idx)                                        \
1324
0
  ((idx) < (context)->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH)
1325
1326
94.5k
static size_t get_max_index(nghttp2_hd_context *context) {
1327
94.5k
  return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
1328
94.5k
}
1329
1330
93.4k
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
1331
93.4k
  assert(INDEX_RANGE_VALID(context, idx));
1332
93.4k
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1333
74.5k
    return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
1334
74.5k
      ->nv;
1335
74.5k
  } else {
1336
18.8k
    const nghttp2_hd_static_entry *ent = &static_table[idx];
1337
18.8k
    return (nghttp2_hd_nv){
1338
18.8k
      .name = (nghttp2_rcbuf *)&ent->name,
1339
18.8k
      .value = (nghttp2_rcbuf *)&ent->value,
1340
18.8k
      .token = ent->token,
1341
18.8k
      .flags = NGHTTP2_NV_FLAG_NONE,
1342
18.8k
    };
1343
18.8k
  }
1344
93.4k
}
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
95.5k
                                           const uint8_t *in) {
1670
95.5k
  inflater->huffman_encoded = (*in & (1 << 7)) != 0;
1671
95.5k
}
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
197k
                                         size_t maxlen) {
1690
197k
  nghttp2_ssize rv;
1691
197k
  uint32_t out;
1692
1693
197k
  *rfin = 0;
1694
1695
197k
  rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
1696
197k
                     inflater->shift, in, last, prefix);
1697
1698
197k
  if (rv == -1) {
1699
100
    DEBUGF("inflatehd: integer decoding failed\n");
1700
100
    return NGHTTP2_ERR_HEADER_COMP;
1701
100
  }
1702
1703
197k
  if (out > maxlen) {
1704
807
    DEBUGF("inflatehd: integer exceeded the maximum value %zu\n", maxlen);
1705
807
    return NGHTTP2_ERR_HEADER_COMP;
1706
807
  }
1707
1708
196k
  inflater->left = out;
1709
1710
196k
  DEBUGF("inflatehd: decoded integer is %u\n", out);
1711
1712
196k
  return rv;
1713
197k
}
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
15.3k
                                          const uint8_t *last) {
1731
15.3k
  nghttp2_ssize readlen;
1732
15.3k
  int fin = 0;
1733
15.3k
  if ((size_t)(last - in) >= inflater->left) {
1734
15.1k
    last = in + inflater->left;
1735
15.1k
    fin = 1;
1736
15.1k
  }
1737
15.3k
  readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
1738
15.3k
                                   (size_t)(last - in), fin);
1739
1740
15.3k
  if (readlen < 0) {
1741
15
    DEBUGF("inflatehd: huffman decoding failed\n");
1742
15
    return readlen;
1743
15
  }
1744
15.2k
  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
15.2k
  inflater->left -= (size_t)readlen;
1750
15.2k
  return readlen;
1751
15.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
79.9k
                                     const uint8_t *last) {
1768
79.9k
  size_t len = nghttp2_min_size((size_t)(last - in), inflater->left);
1769
1770
79.9k
  buf->last = nghttp2_cpymem(buf->last, in, len);
1771
1772
79.9k
  inflater->left -= len;
1773
79.9k
  return (nghttp2_ssize)len;
1774
79.9k
}
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
80.9k
                                      nghttp2_hd_nv *nv_out) {
1782
80.9k
  nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1783
1784
80.9k
  emit_header(nv_out, &nv);
1785
80.9k
}
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
41.0k
                                     nghttp2_hd_nv *nv_out) {
1800
41.0k
  nghttp2_hd_nv nv;
1801
41.0k
  int rv;
1802
1803
41.0k
  if (inflater->no_index) {
1804
2.27k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1805
38.7k
  } else {
1806
38.7k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1807
38.7k
  }
1808
1809
41.0k
  nv.name = inflater->namercbuf;
1810
41.0k
  nv.value = inflater->valuercbuf;
1811
41.0k
  nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
1812
1813
41.0k
  if (inflater->index_required) {
1814
6.04k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1815
1816
6.04k
    if (rv != 0) {
1817
0
      return rv;
1818
0
    }
1819
6.04k
  }
1820
1821
41.0k
  emit_header(nv_out, &nv);
1822
1823
41.0k
  inflater->nv_name_keep = nv.name;
1824
41.0k
  inflater->nv_value_keep = nv.value;
1825
1826
41.0k
  inflater->namercbuf = NULL;
1827
41.0k
  inflater->valuercbuf = NULL;
1828
1829
41.0k
  return 0;
1830
41.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
12.5k
                                     nghttp2_hd_nv *nv_out) {
1845
12.5k
  nghttp2_hd_nv nv;
1846
12.5k
  int rv;
1847
1848
12.5k
  nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1849
1850
12.5k
  if (inflater->no_index) {
1851
573
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1852
11.9k
  } else {
1853
11.9k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1854
11.9k
  }
1855
1856
12.5k
  nghttp2_rcbuf_incref(nv.name);
1857
1858
12.5k
  nv.value = inflater->valuercbuf;
1859
1860
12.5k
  if (inflater->index_required) {
1861
9.69k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1862
9.69k
    if (rv != 0) {
1863
0
      nghttp2_rcbuf_decref(nv.name);
1864
0
      return NGHTTP2_ERR_NOMEM;
1865
0
    }
1866
9.69k
  }
1867
1868
12.5k
  emit_header(nv_out, &nv);
1869
1870
12.5k
  inflater->nv_name_keep = nv.name;
1871
12.5k
  inflater->nv_value_keep = nv.value;
1872
1873
12.5k
  inflater->valuercbuf = NULL;
1874
1875
12.5k
  return 0;
1876
12.5k
}
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
218k
                                       size_t inlen, int in_final) {
1923
218k
  nghttp2_ssize rv = 0;
1924
218k
  const uint8_t *first = in;
1925
218k
  const uint8_t *last = in + inlen;
1926
218k
  int rfin = 0;
1927
218k
  int busy = 0;
1928
218k
  nghttp2_mem *mem;
1929
1930
218k
  mem = inflater->ctx.mem;
1931
1932
218k
  if (inflater->ctx.bad) {
1933
0
    return NGHTTP2_ERR_HEADER_COMP;
1934
0
  }
1935
1936
218k
  DEBUGF("inflatehd: start state=%d\n", inflater->state);
1937
218k
  hd_inflate_keep_free(inflater);
1938
218k
  *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
1939
515k
  for (; in != last || busy;) {
1940
434k
    busy = 0;
1941
434k
    switch (inflater->state) {
1942
16
    case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1943
16
      if ((*in & 0xE0U) != 0x20U) {
1944
2
        DEBUGF("inflatehd: header table size change was expected, but saw "
1945
2
               "0x%02x as first byte",
1946
2
               *in);
1947
2
        rv = NGHTTP2_ERR_HEADER_COMP;
1948
2
        goto fail;
1949
2
      }
1950
    /* fall through */
1951
78.5k
    case NGHTTP2_HD_STATE_INFLATE_START:
1952
141k
    case NGHTTP2_HD_STATE_OPCODE:
1953
141k
      if ((*in & 0xE0U) == 0x20U) {
1954
5.97k
        DEBUGF("inflatehd: header table size change\n");
1955
5.97k
        if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
1956
15
          DEBUGF("inflatehd: header table size change must appear at the head "
1957
15
                 "of header block\n");
1958
15
          rv = NGHTTP2_ERR_HEADER_COMP;
1959
15
          goto fail;
1960
15
        }
1961
5.96k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1962
5.96k
        inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
1963
135k
      } else if (*in & 0x80U) {
1964
81.1k
        DEBUGF("inflatehd: indexed repr\n");
1965
81.1k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1966
81.1k
        inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1967
81.1k
      } else {
1968
54.7k
        if (*in == 0x40U || *in == 0 || *in == 0x10U) {
1969
41.6k
          DEBUGF("inflatehd: literal header repr - new name\n");
1970
41.6k
          inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
1971
41.6k
          inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
1972
41.6k
        } else {
1973
13.1k
          DEBUGF("inflatehd: literal header repr - indexed name\n");
1974
13.1k
          inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
1975
13.1k
          inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1976
13.1k
        }
1977
54.7k
        inflater->index_required = (*in & 0x40) != 0;
1978
54.7k
        inflater->no_index = (*in & 0xF0U) == 0x10U;
1979
54.7k
        DEBUGF("inflatehd: indexing required=%d, no_index=%d\n",
1980
54.7k
               inflater->index_required, inflater->no_index);
1981
54.7k
        if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1982
41.6k
          ++in;
1983
41.6k
        }
1984
54.7k
      }
1985
141k
      inflater->left = 0;
1986
141k
      inflater->shift = 0;
1987
141k
      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
216
        goto fail;
1996
216
      }
1997
6.80k
      in += rv;
1998
6.80k
      if (!rfin) {
1999
1.10k
        goto almost_ok;
2000
1.10k
      }
2001
5.69k
      DEBUGF("inflatehd: table_size=%zu\n", inflater->left);
2002
5.69k
      inflater->min_hd_table_bufsize_max = UINT32_MAX;
2003
5.69k
      inflater->ctx.hd_table_bufsize_max = inflater->left;
2004
5.69k
      hd_context_shrink_table_size(&inflater->ctx, NULL);
2005
5.69k
      inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2006
5.69k
      break;
2007
94.5k
    case NGHTTP2_HD_STATE_READ_INDEX: {
2008
94.5k
      size_t prefixlen;
2009
2010
94.5k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2011
81.1k
        prefixlen = 7;
2012
81.1k
      } else if (inflater->index_required) {
2013
9.95k
        prefixlen = 6;
2014
9.95k
      } else {
2015
3.44k
        prefixlen = 4;
2016
3.44k
      }
2017
2018
94.5k
      rfin = 0;
2019
94.5k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
2020
94.5k
                               get_max_index(&inflater->ctx));
2021
94.5k
      if (rv < 0) {
2022
318
        goto fail;
2023
318
      }
2024
2025
94.1k
      in += rv;
2026
2027
94.1k
      if (!rfin) {
2028
286
        goto almost_ok;
2029
286
      }
2030
2031
93.9k
      if (inflater->left == 0) {
2032
17
        rv = NGHTTP2_ERR_HEADER_COMP;
2033
17
        goto fail;
2034
17
      }
2035
2036
93.8k
      DEBUGF("inflatehd: index=%zu\n", inflater->left);
2037
93.8k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2038
80.9k
        inflater->index = inflater->left;
2039
80.9k
        --inflater->index;
2040
2041
80.9k
        hd_inflate_commit_indexed(inflater, nv_out);
2042
2043
80.9k
        inflater->state = NGHTTP2_HD_STATE_OPCODE;
2044
80.9k
        *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2045
80.9k
        return (nghttp2_ssize)(in - first);
2046
80.9k
      } else {
2047
12.9k
        inflater->index = inflater->left;
2048
12.9k
        --inflater->index;
2049
2050
12.9k
        inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2051
12.9k
      }
2052
12.9k
      break;
2053
93.8k
    }
2054
41.5k
    case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
2055
41.5k
      hd_inflate_set_huffman_encoded(inflater, in);
2056
41.5k
      inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
2057
41.5k
      inflater->left = 0;
2058
41.5k
      inflater->shift = 0;
2059
41.5k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2060
    /* Fall through */
2061
41.7k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
2062
41.7k
      rfin = 0;
2063
41.7k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2064
41.7k
      if (rv < 0) {
2065
186
        goto fail;
2066
186
      }
2067
41.5k
      in += rv;
2068
41.5k
      if (!rfin) {
2069
212
        DEBUGF("inflatehd: integer not fully decoded. current=%zu\n",
2070
212
               inflater->left);
2071
2072
212
        goto almost_ok;
2073
212
      }
2074
2075
41.3k
      if (inflater->huffman_encoded) {
2076
8.45k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2077
2078
8.45k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
2079
2080
8.45k
        rv = nghttp2_rcbuf_new(
2081
8.45k
          &inflater->namercbuf,
2082
8.45k
          nghttp2_huff_estimate_decode_length(inflater->left) + 1, mem);
2083
32.8k
      } else {
2084
32.8k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
2085
32.8k
        rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
2086
32.8k
      }
2087
2088
41.3k
      if (rv != 0) {
2089
0
        goto fail;
2090
0
      }
2091
2092
41.3k
      nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
2093
41.3k
                            inflater->namercbuf->len);
2094
2095
41.3k
      break;
2096
8.43k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
2097
8.43k
      rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
2098
8.43k
      if (rv < 0) {
2099
12
        goto fail;
2100
12
      }
2101
2102
8.41k
      in += rv;
2103
2104
8.41k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2105
2106
8.41k
      if (inflater->left) {
2107
59
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2108
2109
59
        goto almost_ok;
2110
59
      }
2111
2112
8.35k
      *inflater->namebuf.last = '\0';
2113
8.35k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2114
2115
8.35k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2116
2117
8.35k
      break;
2118
32.8k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
2119
32.8k
      rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
2120
32.8k
      if (rv < 0) {
2121
0
        goto fail;
2122
0
      }
2123
2124
32.8k
      in += rv;
2125
2126
32.8k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2127
32.8k
      if (inflater->left) {
2128
73
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2129
2130
73
        goto almost_ok;
2131
73
      }
2132
2133
32.7k
      *inflater->namebuf.last = '\0';
2134
32.7k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2135
2136
32.7k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2137
2138
32.7k
      break;
2139
54.0k
    case NGHTTP2_HD_STATE_CHECK_VALUELEN:
2140
54.0k
      hd_inflate_set_huffman_encoded(inflater, in);
2141
54.0k
      inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
2142
54.0k
      inflater->left = 0;
2143
54.0k
      inflater->shift = 0;
2144
54.0k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2145
    /* Fall through */
2146
54.1k
    case NGHTTP2_HD_STATE_READ_VALUELEN:
2147
54.1k
      rfin = 0;
2148
54.1k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2149
54.1k
      if (rv < 0) {
2150
187
        goto fail;
2151
187
      }
2152
2153
53.9k
      in += rv;
2154
2155
53.9k
      if (!rfin) {
2156
219
        goto almost_ok;
2157
219
      }
2158
2159
53.7k
      DEBUGF("inflatehd: valuelen=%zu\n", inflater->left);
2160
2161
53.7k
      if (inflater->huffman_encoded) {
2162
6.86k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2163
2164
6.86k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
2165
2166
6.86k
        rv = nghttp2_rcbuf_new(
2167
6.86k
          &inflater->valuercbuf,
2168
6.86k
          nghttp2_huff_estimate_decode_length(inflater->left) + 1, mem);
2169
46.9k
      } else {
2170
46.9k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
2171
2172
46.9k
        rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
2173
46.9k
      }
2174
2175
53.7k
      if (rv != 0) {
2176
0
        goto fail;
2177
0
      }
2178
2179
53.7k
      nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
2180
53.7k
                            inflater->valuercbuf->len);
2181
2182
53.7k
      busy = 1;
2183
2184
53.7k
      break;
2185
6.88k
    case NGHTTP2_HD_STATE_READ_VALUEHUFF:
2186
6.88k
      rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
2187
6.88k
      if (rv < 0) {
2188
15
        goto fail;
2189
15
      }
2190
2191
6.86k
      in += rv;
2192
2193
6.86k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2194
2195
6.86k
      if (inflater->left) {
2196
93
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2197
2198
93
        goto almost_ok;
2199
93
      }
2200
2201
6.77k
      *inflater->valuebuf.last = '\0';
2202
6.77k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2203
2204
6.77k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2205
3.02k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2206
3.75k
      } else {
2207
3.75k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2208
3.75k
      }
2209
2210
6.77k
      if (rv != 0) {
2211
0
        goto fail;
2212
0
      }
2213
2214
6.77k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2215
6.77k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2216
2217
6.77k
      return (nghttp2_ssize)(in - first);
2218
47.1k
    case NGHTTP2_HD_STATE_READ_VALUE:
2219
47.1k
      rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
2220
47.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
47.1k
      in += rv;
2227
2228
47.1k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2229
2230
47.1k
      if (inflater->left) {
2231
370
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2232
370
        goto almost_ok;
2233
370
      }
2234
2235
46.8k
      *inflater->valuebuf.last = '\0';
2236
46.8k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2237
2238
46.8k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2239
38.0k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2240
38.0k
      } else {
2241
8.78k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2242
8.78k
      }
2243
2244
46.8k
      if (rv != 0) {
2245
0
        goto fail;
2246
0
      }
2247
2248
46.8k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2249
46.8k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2250
2251
46.8k
      return (nghttp2_ssize)(in - first);
2252
434k
    }
2253
434k
  }
2254
2255
218k
  assert(in == last);
2256
2257
80.7k
  DEBUGF("inflatehd: all input bytes were processed\n");
2258
2259
80.7k
  if (in_final) {
2260
76.7k
    DEBUGF("inflatehd: in_final set\n");
2261
2262
76.7k
    if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
2263
8.79k
        inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
2264
12
      DEBUGF("inflatehd: unacceptable state=%d\n", inflater->state);
2265
12
      rv = NGHTTP2_ERR_HEADER_COMP;
2266
2267
12
      goto fail;
2268
12
    }
2269
76.7k
    *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
2270
76.7k
  }
2271
80.7k
  return (nghttp2_ssize)(in - first);
2272
2273
2.41k
almost_ok:
2274
2.41k
  if (in_final) {
2275
11
    DEBUGF("inflatehd: input ended prematurely\n");
2276
2277
11
    rv = NGHTTP2_ERR_HEADER_COMP;
2278
2279
11
    goto fail;
2280
11
  }
2281
2.40k
  return (nghttp2_ssize)(in - first);
2282
2283
991
fail:
2284
991
  DEBUGF("inflatehd: error return %td\n", rv);
2285
2286
991
  inflater->ctx.bad = 1;
2287
991
  return rv;
2288
2.41k
}
2289
2290
76.7k
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
2291
76.7k
  hd_inflate_keep_free(inflater);
2292
76.7k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2293
76.7k
  return 0;
2294
76.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
}