Coverage Report

Created: 2026-01-09 06:13

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