Coverage Report

Created: 2026-02-26 07:02

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
48.1k
static int memeq(const void *s1, const void *s2, size_t n) {
115
48.1k
  return memcmp(s1, s2, n) == 0;
116
48.1k
}
117
118
/*
119
 * This function was generated by genlibtokenlookup.py.  Inspired by
120
 * h2o header lookup.  https://github.com/h2o/h2o
121
 */
122
86.6k
static int32_t lookup_token(const uint8_t *name, size_t namelen) {
123
86.6k
  switch (namelen) {
124
1.13k
  case 2:
125
1.13k
    switch (name[1]) {
126
843
    case 'e':
127
843
      if (memeq("t", name, 1)) {
128
601
        return NGHTTP2_TOKEN_TE;
129
601
      }
130
242
      break;
131
1.13k
    }
132
536
    break;
133
1.88k
  case 3:
134
1.88k
    switch (name[2]) {
135
685
    case 'a':
136
685
      if (memeq("vi", name, 2)) {
137
234
        return NGHTTP2_TOKEN_VIA;
138
234
      }
139
451
      break;
140
451
    case 'e':
141
451
      if (memeq("ag", name, 2)) {
142
209
        return NGHTTP2_TOKEN_AGE;
143
209
      }
144
242
      break;
145
1.88k
    }
146
1.44k
    break;
147
5.08k
  case 4:
148
5.08k
    switch (name[3]) {
149
856
    case 'e':
150
856
      if (memeq("dat", name, 3)) {
151
593
        return NGHTTP2_TOKEN_DATE;
152
593
      }
153
263
      break;
154
519
    case 'g':
155
519
      if (memeq("eta", name, 3)) {
156
203
        return NGHTTP2_TOKEN_ETAG;
157
203
      }
158
316
      break;
159
364
    case 'k':
160
364
      if (memeq("lin", name, 3)) {
161
239
        return NGHTTP2_TOKEN_LINK;
162
239
      }
163
125
      break;
164
327
    case 'm':
165
327
      if (memeq("fro", name, 3)) {
166
253
        return NGHTTP2_TOKEN_FROM;
167
253
      }
168
74
      break;
169
448
    case 't':
170
448
      if (memeq("hos", name, 3)) {
171
191
        return NGHTTP2_TOKEN_HOST;
172
191
      }
173
257
      break;
174
640
    case 'y':
175
640
      if (memeq("var", name, 3)) {
176
293
        return NGHTTP2_TOKEN_VARY;
177
293
      }
178
347
      break;
179
5.08k
    }
180
3.30k
    break;
181
3.30k
  case 5:
182
1.88k
    switch (name[4]) {
183
489
    case 'e':
184
489
      if (memeq("rang", name, 4)) {
185
200
        return NGHTTP2_TOKEN_RANGE;
186
200
      }
187
289
      break;
188
490
    case 'h':
189
490
      if (memeq(":pat", name, 4)) {
190
197
        return NGHTTP2_TOKEN__PATH;
191
197
      }
192
293
      break;
193
489
    case 'w':
194
489
      if (memeq("allo", name, 4)) {
195
232
        return NGHTTP2_TOKEN_ALLOW;
196
232
      }
197
257
      break;
198
1.88k
    }
199
1.25k
    break;
200
3.34k
  case 6:
201
3.34k
    switch (name[5]) {
202
289
    case 'e':
203
289
      if (memeq("cooki", name, 5)) {
204
66
        return NGHTTP2_TOKEN_COOKIE;
205
66
      }
206
223
      break;
207
390
    case 'r':
208
390
      if (memeq("serve", name, 5)) {
209
194
        return NGHTTP2_TOKEN_SERVER;
210
194
      }
211
196
      break;
212
1.28k
    case 't':
213
1.28k
      if (memeq("accep", name, 5)) {
214
821
        return NGHTTP2_TOKEN_ACCEPT;
215
821
      }
216
460
      if (memeq("expec", name, 5)) {
217
251
        return NGHTTP2_TOKEN_EXPECT;
218
251
      }
219
209
      break;
220
3.34k
    }
221
2.01k
    break;
222
3.65k
  case 7:
223
3.65k
    switch (name[6]) {
224
379
    case 'd':
225
379
      if (memeq(":metho", name, 6)) {
226
194
        return NGHTTP2_TOKEN__METHOD;
227
194
      }
228
185
      break;
229
1.28k
    case 'e':
230
1.28k
      if (memeq(":schem", name, 6)) {
231
195
        return NGHTTP2_TOKEN__SCHEME;
232
195
      }
233
1.08k
      if (memeq("upgrad", name, 6)) {
234
306
        return NGHTTP2_TOKEN_UPGRADE;
235
306
      }
236
779
      break;
237
779
    case 'h':
238
697
      if (memeq("refres", name, 6)) {
239
489
        return NGHTTP2_TOKEN_REFRESH;
240
489
      }
241
208
      break;
242
395
    case 'r':
243
395
      if (memeq("refere", name, 6)) {
244
194
        return NGHTTP2_TOKEN_REFERER;
245
194
      }
246
201
      break;
247
475
    case 's':
248
475
      if (memeq(":statu", name, 6)) {
249
66
        return NGHTTP2_TOKEN__STATUS;
250
66
      }
251
409
      if (memeq("expire", name, 6)) {
252
194
        return NGHTTP2_TOKEN_EXPIRES;
253
194
      }
254
215
      break;
255
3.65k
    }
256
2.01k
    break;
257
7.01k
  case 8:
258
7.01k
    switch (name[7]) {
259
1.01k
    case 'e':
260
1.01k
      if (memeq("if-rang", name, 7)) {
261
271
        return NGHTTP2_TOKEN_IF_RANGE;
262
271
      }
263
747
      break;
264
747
    case 'h':
265
418
      if (memeq("if-matc", name, 7)) {
266
212
        return NGHTTP2_TOKEN_IF_MATCH;
267
212
      }
268
206
      break;
269
388
    case 'n':
270
388
      if (memeq("locatio", name, 7)) {
271
195
        return NGHTTP2_TOKEN_LOCATION;
272
195
      }
273
193
      break;
274
4.83k
    case 'y':
275
4.83k
      if (memeq("priorit", name, 7)) {
276
4.61k
        return NGHTTP2_TOKEN_PRIORITY;
277
4.61k
      }
278
216
      break;
279
7.01k
    }
280
1.72k
    break;
281
1.72k
  case 9:
282
1.02k
    switch (name[8]) {
283
690
    case 'l':
284
690
      if (memeq(":protoco", name, 8)) {
285
579
        return NGHTTP2_TOKEN__PROTOCOL;
286
579
      }
287
111
      break;
288
1.02k
    }
289
446
    break;
290
5.98k
  case 10:
291
5.98k
    switch (name[9]) {
292
2.26k
    case 'e':
293
2.26k
      if (memeq("keep-aliv", name, 9)) {
294
778
        return NGHTTP2_TOKEN_KEEP_ALIVE;
295
778
      }
296
1.48k
      if (memeq("set-cooki", name, 9)) {
297
194
        return NGHTTP2_TOKEN_SET_COOKIE;
298
194
      }
299
1.29k
      break;
300
1.29k
    case 'n':
301
571
      if (memeq("connectio", name, 9)) {
302
70
        return NGHTTP2_TOKEN_CONNECTION;
303
70
      }
304
501
      break;
305
1.17k
    case 't':
306
1.17k
      if (memeq("user-agen", name, 9)) {
307
951
        return NGHTTP2_TOKEN_USER_AGENT;
308
951
      }
309
224
      break;
310
1.14k
    case 'y':
311
1.14k
      if (memeq(":authorit", name, 9)) {
312
286
        return NGHTTP2_TOKEN__AUTHORITY;
313
286
      }
314
863
      break;
315
5.98k
    }
316
3.70k
    break;
317
3.70k
  case 11:
318
500
    switch (name[10]) {
319
286
    case 'r':
320
286
      if (memeq("retry-afte", name, 10)) {
321
80
        return NGHTTP2_TOKEN_RETRY_AFTER;
322
80
      }
323
206
      break;
324
500
    }
325
420
    break;
326
1.07k
  case 12:
327
1.07k
    switch (name[11]) {
328
448
    case 'e':
329
448
      if (memeq("content-typ", name, 11)) {
330
210
        return NGHTTP2_TOKEN_CONTENT_TYPE;
331
210
      }
332
238
      break;
333
449
    case 's':
334
449
      if (memeq("max-forward", name, 11)) {
335
242
        return NGHTTP2_TOKEN_MAX_FORWARDS;
336
242
      }
337
207
      break;
338
1.07k
    }
339
621
    break;
340
3.49k
  case 13:
341
3.49k
    switch (name[12]) {
342
436
    case 'd':
343
436
      if (memeq("last-modifie", name, 12)) {
344
215
        return NGHTTP2_TOKEN_LAST_MODIFIED;
345
215
      }
346
221
      break;
347
458
    case 'e':
348
458
      if (memeq("content-rang", name, 12)) {
349
205
        return NGHTTP2_TOKEN_CONTENT_RANGE;
350
205
      }
351
253
      break;
352
468
    case 'h':
353
468
      if (memeq("if-none-matc", name, 12)) {
354
254
        return NGHTTP2_TOKEN_IF_NONE_MATCH;
355
254
      }
356
214
      break;
357
407
    case 'l':
358
407
      if (memeq("cache-contro", name, 12)) {
359
199
        return NGHTTP2_TOKEN_CACHE_CONTROL;
360
199
      }
361
208
      break;
362
824
    case 'n':
363
824
      if (memeq("authorizatio", name, 12)) {
364
583
        return NGHTTP2_TOKEN_AUTHORIZATION;
365
583
      }
366
241
      break;
367
631
    case 's':
368
631
      if (memeq("accept-range", name, 12)) {
369
402
        return NGHTTP2_TOKEN_ACCEPT_RANGES;
370
402
      }
371
229
      break;
372
3.49k
    }
373
1.63k
    break;
374
1.63k
  case 14:
375
1.46k
    switch (name[13]) {
376
515
    case 'h':
377
515
      if (memeq("content-lengt", name, 13)) {
378
66
        return NGHTTP2_TOKEN_CONTENT_LENGTH;
379
66
      }
380
449
      break;
381
686
    case 't':
382
686
      if (memeq("accept-charse", name, 13)) {
383
194
        return NGHTTP2_TOKEN_ACCEPT_CHARSET;
384
194
      }
385
492
      break;
386
1.46k
    }
387
1.20k
    break;
388
1.52k
  case 15:
389
1.52k
    switch (name[14]) {
390
440
    case 'e':
391
440
      if (memeq("accept-languag", name, 14)) {
392
204
        return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
393
204
      }
394
236
      break;
395
807
    case 'g':
396
807
      if (memeq("accept-encodin", name, 14)) {
397
194
        return NGHTTP2_TOKEN_ACCEPT_ENCODING;
398
194
      }
399
613
      break;
400
1.52k
    }
401
1.13k
    break;
402
6.56k
  case 16:
403
6.56k
    switch (name[15]) {
404
3.10k
    case 'e':
405
3.10k
      if (memeq("content-languag", name, 15)) {
406
872
        return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
407
872
      }
408
2.22k
      if (memeq("www-authenticat", name, 15)) {
409
964
        return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
410
964
      }
411
1.26k
      break;
412
1.26k
    case 'g':
413
575
      if (memeq("content-encodin", name, 15)) {
414
355
        return NGHTTP2_TOKEN_CONTENT_ENCODING;
415
355
      }
416
220
      break;
417
953
    case 'n':
418
953
      if (memeq("content-locatio", name, 15)) {
419
196
        return NGHTTP2_TOKEN_CONTENT_LOCATION;
420
196
      }
421
757
      if (memeq("proxy-connectio", name, 15)) {
422
330
        return NGHTTP2_TOKEN_PROXY_CONNECTION;
423
330
      }
424
427
      break;
425
6.56k
    }
426
3.85k
    break;
427
3.85k
  case 17:
428
1.60k
    switch (name[16]) {
429
389
    case 'e':
430
389
      if (memeq("if-modified-sinc", name, 16)) {
431
195
        return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
432
195
      }
433
194
      break;
434
693
    case 'g':
435
693
      if (memeq("transfer-encodin", name, 16)) {
436
503
        return NGHTTP2_TOKEN_TRANSFER_ENCODING;
437
503
      }
438
190
      break;
439
1.60k
    }
440
903
    break;
441
1.03k
  case 18:
442
1.03k
    switch (name[17]) {
443
773
    case 'e':
444
773
      if (memeq("proxy-authenticat", name, 17)) {
445
213
        return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
446
213
      }
447
560
      break;
448
1.03k
    }
449
822
    break;
450
2.57k
  case 19:
451
2.57k
    switch (name[18]) {
452
545
    case 'e':
453
545
      if (memeq("if-unmodified-sinc", name, 18)) {
454
194
        return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
455
194
      }
456
351
      break;
457
1.40k
    case 'n':
458
1.40k
      if (memeq("content-dispositio", name, 18)) {
459
204
        return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
460
204
      }
461
1.20k
      if (memeq("proxy-authorizatio", name, 18)) {
462
848
        return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
463
848
      }
464
353
      break;
465
2.57k
    }
466
1.32k
    break;
467
1.32k
  case 25:
468
740
    switch (name[24]) {
469
512
    case 'y':
470
512
      if (memeq("strict-transport-securit", name, 24)) {
471
255
        return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
472
255
      }
473
257
      break;
474
740
    }
475
485
    break;
476
780
  case 27:
477
780
    switch (name[26]) {
478
472
    case 'n':
479
472
      if (memeq("access-control-allow-origi", name, 26)) {
480
238
        return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
481
238
      }
482
234
      break;
483
780
    }
484
542
    break;
485
86.6k
  }
486
63.6k
  return -1;
487
86.6k
}
488
489
25.4k
void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
490
25.4k
  ent->nv = *nv;
491
25.4k
  ent->cnv.name = nv->name->base;
492
25.4k
  ent->cnv.namelen = nv->name->len;
493
25.4k
  ent->cnv.value = nv->value->base;
494
25.4k
  ent->cnv.valuelen = nv->value->len;
495
25.4k
  ent->cnv.flags = nv->flags;
496
25.4k
  ent->next = NULL;
497
25.4k
  ent->hash = 0;
498
499
25.4k
  nghttp2_rcbuf_incref(ent->nv.name);
500
25.4k
  nghttp2_rcbuf_incref(ent->nv.value);
501
25.4k
}
502
503
25.4k
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
504
25.4k
  nghttp2_rcbuf_decref(ent->nv.value);
505
25.4k
  nghttp2_rcbuf_decref(ent->nv.name);
506
25.4k
}
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
11.7k
static void hd_map_init(nghttp2_hd_map *map) {
532
11.7k
  memset(map, 0, sizeof(nghttp2_hd_map));
533
11.7k
}
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
23.4k
                           nghttp2_mem *mem) {
597
23.4k
  size_t size;
598
23.4k
  const size_t max_size = SIZE_MAX / sizeof(nghttp2_hd_entry *);
599
600
23.4k
  if (bufsize > max_size) {
601
0
    return NGHTTP2_ERR_NOMEM;
602
0
  }
603
604
187k
  for (size = 1; size < bufsize; size <<= 1)
605
163k
    ;
606
607
23.4k
  if (size > max_size) {
608
0
    return NGHTTP2_ERR_NOMEM;
609
0
  }
610
611
23.4k
  ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
612
23.4k
  if (ringbuf->buffer == NULL) {
613
0
    return NGHTTP2_ERR_NOMEM;
614
0
  }
615
23.4k
  ringbuf->mask = size - 1;
616
23.4k
  ringbuf->first = 0;
617
23.4k
  ringbuf->len = 0;
618
23.4k
  return 0;
619
23.4k
}
620
621
static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
622
58.9k
                                        size_t idx) {
623
58.9k
  assert(idx < ringbuf->len);
624
58.9k
  return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
625
58.9k
}
626
627
static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
628
25.4k
                              nghttp2_mem *mem) {
629
25.4k
  size_t i;
630
25.4k
  size_t size;
631
25.4k
  nghttp2_hd_entry **buffer;
632
633
25.4k
  if (ringbuf->mask + 1 >= bufsize) {
634
25.4k
    return 0;
635
25.4k
  }
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
23.4k
static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
653
23.4k
  size_t i;
654
23.4k
  if (ringbuf == NULL) {
655
0
    return;
656
0
  }
657
40.0k
  for (i = 0; i < ringbuf->len; ++i) {
658
16.6k
    nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
659
660
16.6k
    nghttp2_hd_entry_free(ent);
661
16.6k
    nghttp2_mem_free(mem, ent);
662
16.6k
  }
663
23.4k
  nghttp2_mem_free(mem, ringbuf->buffer);
664
23.4k
}
665
666
static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
667
25.4k
                                 nghttp2_hd_entry *ent, nghttp2_mem *mem) {
668
25.4k
  int rv;
669
670
25.4k
  rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
671
672
25.4k
  if (rv != 0) {
673
0
    return rv;
674
0
  }
675
676
25.4k
  ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
677
25.4k
  ++ringbuf->len;
678
679
25.4k
  return 0;
680
25.4k
}
681
682
8.83k
static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
683
8.83k
  assert(ringbuf->len > 0);
684
8.83k
  --ringbuf->len;
685
8.83k
}
686
687
23.4k
static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
688
23.4k
  int rv;
689
23.4k
  context->mem = mem;
690
23.4k
  context->bad = 0;
691
23.4k
  context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
692
23.4k
  rv = hd_ringbuf_init(
693
23.4k
    &context->hd_table,
694
23.4k
    context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
695
23.4k
  if (rv != 0) {
696
0
    return rv;
697
0
  }
698
699
23.4k
  context->hd_table_bufsize = 0;
700
23.4k
  context->next_seq = 0;
701
702
23.4k
  return 0;
703
23.4k
}
704
705
23.4k
static void hd_context_free(nghttp2_hd_context *context) {
706
23.4k
  hd_ringbuf_free(&context->hd_table, context->mem);
707
23.4k
}
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
11.7k
                             nghttp2_mem *mem) {
717
11.7k
  int rv;
718
11.7k
  rv = hd_context_init(&deflater->ctx, mem);
719
11.7k
  if (rv != 0) {
720
0
    return rv;
721
0
  }
722
723
11.7k
  hd_map_init(&deflater->map);
724
725
11.7k
  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
11.7k
  } else {
729
11.7k
    deflater->notify_table_size_change = 0;
730
11.7k
  }
731
732
11.7k
  deflater->deflate_hd_table_bufsize_max = max_deflate_dynamic_table_size;
733
11.7k
  deflater->min_hd_table_bufsize_max = UINT32_MAX;
734
735
11.7k
  return 0;
736
11.7k
}
737
738
11.7k
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
739
11.7k
  int rv;
740
741
11.7k
  rv = hd_context_init(&inflater->ctx, mem);
742
11.7k
  if (rv != 0) {
743
0
    goto fail;
744
0
  }
745
746
11.7k
  inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
747
11.7k
  inflater->min_hd_table_bufsize_max = UINT32_MAX;
748
749
11.7k
  inflater->nv_name_keep = NULL;
750
11.7k
  inflater->nv_value_keep = NULL;
751
752
11.7k
  inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
753
11.7k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
754
755
11.7k
  nghttp2_buf_init(&inflater->namebuf);
756
11.7k
  nghttp2_buf_init(&inflater->valuebuf);
757
758
11.7k
  inflater->namercbuf = NULL;
759
11.7k
  inflater->valuercbuf = NULL;
760
761
11.7k
  inflater->huffman_encoded = 0;
762
11.7k
  inflater->index = 0;
763
11.7k
  inflater->left = 0;
764
11.7k
  inflater->shift = 0;
765
11.7k
  inflater->index_required = 0;
766
11.7k
  inflater->no_index = 0;
767
768
11.7k
  return 0;
769
770
0
fail:
771
0
  return rv;
772
11.7k
}
773
774
301k
static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
775
301k
  nghttp2_rcbuf_decref(inflater->nv_value_keep);
776
301k
  nghttp2_rcbuf_decref(inflater->nv_name_keep);
777
778
301k
  inflater->nv_value_keep = NULL;
779
301k
  inflater->nv_name_keep = NULL;
780
301k
}
781
782
11.7k
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
783
11.7k
  hd_context_free(&deflater->ctx);
784
11.7k
}
785
786
11.7k
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
787
11.7k
  hd_inflate_keep_free(inflater);
788
789
11.7k
  nghttp2_rcbuf_decref(inflater->valuercbuf);
790
11.7k
  nghttp2_rcbuf_decref(inflater->namercbuf);
791
792
11.7k
  hd_context_free(&inflater->ctx);
793
11.7k
}
794
795
35.8k
static size_t entry_room(size_t namelen, size_t valuelen) {
796
35.8k
  return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
797
35.8k
}
798
799
252k
static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
800
252k
  DEBUGF("inflatehd: header emission: %s: %s\n", nv->name->base,
801
252k
         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
252k
  *nv_out = *nv;
805
252k
}
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
374k
                                   size_t prefix) {
870
374k
  uint32_t k = (uint8_t)((1 << prefix) - 1);
871
374k
  uint32_t n = initial;
872
374k
  const uint8_t *start = in;
873
874
374k
  *shift_ptr = 0;
875
374k
  *fin = 0;
876
877
374k
  if (n == 0) {
878
373k
    if ((*in & k) != k) {
879
366k
      *res = (*in) & k;
880
366k
      *fin = 1;
881
366k
      return 1;
882
366k
    }
883
884
6.48k
    n = k;
885
886
6.48k
    if (++in == last) {
887
129
      *res = n;
888
129
      return (nghttp2_ssize)(in - start);
889
129
    }
890
6.48k
  }
891
892
19.6k
  for (; in != last; ++in, shift += 7) {
893
18.4k
    uint32_t add = *in & 0x7f;
894
895
18.4k
    if (shift >= 32) {
896
37
      DEBUGF("inflate: shift exponent overflow\n");
897
37
      return -1;
898
37
    }
899
900
18.4k
    if ((UINT32_MAX >> shift) < add) {
901
53
      DEBUGF("inflate: integer overflow on shift\n");
902
53
      return -1;
903
53
    }
904
905
18.3k
    add <<= shift;
906
907
18.3k
    if (UINT32_MAX - add < n) {
908
39
      DEBUGF("inflate: integer overflow on addition\n");
909
39
      return -1;
910
39
    }
911
912
18.3k
    n += add;
913
914
18.3k
    if ((*in & (1 << 7)) == 0) {
915
5.87k
      break;
916
5.87k
    }
917
18.3k
  }
918
919
7.07k
  *shift_ptr = shift;
920
921
7.07k
  if (in == last) {
922
1.19k
    *res = n;
923
1.19k
    return (nghttp2_ssize)(in - start);
924
1.19k
  }
925
926
5.87k
  *res = n;
927
5.87k
  *fin = 1;
928
5.87k
  return (nghttp2_ssize)(in + 1 - start);
929
7.07k
}
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
26.9k
                                    uint32_t hash) {
1117
26.9k
  int rv;
1118
26.9k
  nghttp2_hd_entry *new_ent;
1119
26.9k
  size_t room;
1120
26.9k
  nghttp2_mem *mem;
1121
1122
26.9k
  mem = context->mem;
1123
26.9k
  room = entry_room(nv->name->len, nv->value->len);
1124
1125
35.2k
  while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
1126
9.77k
         context->hd_table.len > 0) {
1127
8.22k
    size_t idx = context->hd_table.len - 1;
1128
8.22k
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1129
1130
8.22k
    context->hd_table_bufsize -=
1131
8.22k
      entry_room(ent->nv.name->len, ent->nv.value->len);
1132
1133
8.22k
    DEBUGF("hpack: remove item from header table: %s: %s\n",
1134
8.22k
           (char *)ent->nv.name->base, (char *)ent->nv.value->base);
1135
1136
8.22k
    hd_ringbuf_pop_back(&context->hd_table);
1137
8.22k
    if (map) {
1138
0
      hd_map_remove(map, ent);
1139
0
    }
1140
1141
8.22k
    nghttp2_hd_entry_free(ent);
1142
8.22k
    nghttp2_mem_free(mem, ent);
1143
8.22k
  }
1144
1145
26.9k
  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
1.54k
    return 0;
1149
1.54k
  }
1150
1151
25.4k
  new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
1152
25.4k
  if (new_ent == NULL) {
1153
0
    return NGHTTP2_ERR_NOMEM;
1154
0
  }
1155
1156
25.4k
  nghttp2_hd_entry_init(new_ent, nv);
1157
1158
25.4k
  rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
1159
1160
25.4k
  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
25.4k
  new_ent->seq = context->next_seq++;
1168
25.4k
  new_ent->hash = hash;
1169
1170
25.4k
  if (map) {
1171
0
    hd_map_insert(map, new_ent);
1172
0
  }
1173
1174
25.4k
  context->hd_table_bufsize += room;
1175
1176
25.4k
  return 0;
1177
25.4k
}
1178
1179
typedef struct {
1180
  nghttp2_ssize index;
1181
  /* Nonzero if both name and value are matched. */
1182
  int name_value_match;
1183
} search_result;
1184
1185
static search_result search_static_table(const nghttp2_nv *nv, int32_t token,
1186
0
                                         int name_only) {
1187
0
  search_result res = {token, 0};
1188
0
  int i;
1189
0
  const nghttp2_hd_static_entry *ent;
1190
1191
0
  if (name_only) {
1192
0
    return res;
1193
0
  }
1194
1195
0
  for (i = token;
1196
0
       i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token;
1197
0
       ++i) {
1198
0
    ent = &static_table[i];
1199
0
    if (ent->value.len == nv->valuelen &&
1200
0
        memcmp(ent->value.base, nv->value, nv->valuelen) == 0) {
1201
0
      res.index = i;
1202
0
      res.name_value_match = 1;
1203
0
      return res;
1204
0
    }
1205
0
  }
1206
0
  return res;
1207
0
}
1208
1209
static search_result search_hd_table(nghttp2_hd_context *context,
1210
                                     const nghttp2_nv *nv, int32_t token,
1211
                                     int indexing_mode, nghttp2_hd_map *map,
1212
0
                                     uint32_t hash) {
1213
0
  search_result res = {-1, 0};
1214
0
  const nghttp2_hd_entry *ent;
1215
0
  int exact_match;
1216
0
  int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
1217
1218
0
  exact_match = 0;
1219
0
  ent = hd_map_find(map, &exact_match, nv, token, hash, name_only);
1220
1221
0
  if (!exact_match && token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
1222
0
    return search_static_table(nv, token, name_only);
1223
0
  }
1224
1225
0
  if (ent == NULL) {
1226
0
    return res;
1227
0
  }
1228
1229
0
  res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq +
1230
0
                              NGHTTP2_STATIC_TABLE_LENGTH);
1231
0
  res.name_value_match = exact_match;
1232
1233
0
  return res;
1234
0
}
1235
1236
static void hd_context_shrink_table_size(nghttp2_hd_context *context,
1237
4.94k
                                         nghttp2_hd_map *map) {
1238
4.94k
  nghttp2_mem *mem;
1239
1240
4.94k
  mem = context->mem;
1241
1242
5.55k
  while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
1243
611
         context->hd_table.len > 0) {
1244
611
    size_t idx = context->hd_table.len - 1;
1245
611
    nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
1246
611
    context->hd_table_bufsize -=
1247
611
      entry_room(ent->nv.name->len, ent->nv.value->len);
1248
611
    hd_ringbuf_pop_back(&context->hd_table);
1249
611
    if (map) {
1250
0
      hd_map_remove(map, ent);
1251
0
    }
1252
1253
611
    nghttp2_hd_entry_free(ent);
1254
611
    nghttp2_mem_free(mem, ent);
1255
611
  }
1256
4.94k
}
1257
1258
int nghttp2_hd_deflate_change_table_size(
1259
2.20k
  nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
1260
2.20k
  size_t next_bufsize = nghttp2_min_size(
1261
2.20k
    settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
1262
1263
2.20k
  deflater->ctx.hd_table_bufsize_max = next_bufsize;
1264
1265
2.20k
  deflater->min_hd_table_bufsize_max =
1266
2.20k
    nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
1267
1268
2.20k
  deflater->notify_table_size_change = 1;
1269
1270
2.20k
  hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
1271
2.20k
  return 0;
1272
2.20k
}
1273
1274
int nghttp2_hd_inflate_change_table_size(
1275
93
  nghttp2_hd_inflater *inflater, size_t settings_max_dynamic_table_size) {
1276
93
  switch (inflater->state) {
1277
18
  case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1278
93
  case NGHTTP2_HD_STATE_INFLATE_START:
1279
93
    break;
1280
0
  default:
1281
0
    return NGHTTP2_ERR_INVALID_STATE;
1282
93
  }
1283
1284
93
  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
93
  if (inflater->ctx.hd_table_bufsize_max > settings_max_dynamic_table_size) {
1294
72
    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
72
    inflater->min_hd_table_bufsize_max = settings_max_dynamic_table_size;
1298
1299
72
    inflater->ctx.hd_table_bufsize_max = settings_max_dynamic_table_size;
1300
1301
72
    hd_context_shrink_table_size(&inflater->ctx, NULL);
1302
72
  }
1303
1304
93
  return 0;
1305
93
}
1306
1307
#define INDEX_RANGE_VALID(context, idx)                                        \
1308
0
  ((idx) < (context)->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH)
1309
1310
166k
static size_t get_max_index(nghttp2_hd_context *context) {
1311
166k
  return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
1312
166k
}
1313
1314
165k
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
1315
165k
  assert(INDEX_RANGE_VALID(context, idx));
1316
165k
  if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
1317
33.5k
    return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
1318
33.5k
      ->nv;
1319
131k
  } else {
1320
131k
    const nghttp2_hd_static_entry *ent = &static_table[idx];
1321
131k
    nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name,
1322
131k
                        (nghttp2_rcbuf *)&ent->value, ent->token,
1323
131k
                        NGHTTP2_NV_FLAG_NONE};
1324
131k
    return nv;
1325
131k
  }
1326
165k
}
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
204k
                                           const uint8_t *in) {
1652
204k
  inflater->huffman_encoded = (*in & (1 << 7)) != 0;
1653
204k
}
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
374k
                                         size_t maxlen) {
1672
374k
  nghttp2_ssize rv;
1673
374k
  uint32_t out;
1674
1675
374k
  *rfin = 0;
1676
1677
374k
  rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
1678
374k
                     inflater->shift, in, last, prefix);
1679
1680
374k
  if (rv == -1) {
1681
129
    DEBUGF("inflatehd: integer decoding failed\n");
1682
129
    return NGHTTP2_ERR_HEADER_COMP;
1683
129
  }
1684
1685
374k
  if (out > maxlen) {
1686
778
    DEBUGF("inflatehd: integer exceeded the maximum value %zu\n", maxlen);
1687
778
    return NGHTTP2_ERR_HEADER_COMP;
1688
778
  }
1689
1690
373k
  inflater->left = out;
1691
1692
373k
  DEBUGF("inflatehd: decoded integer is %u\n", out);
1693
1694
373k
  return rv;
1695
374k
}
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
21.0k
                                          const uint8_t *last) {
1713
21.0k
  nghttp2_ssize readlen;
1714
21.0k
  int fin = 0;
1715
21.0k
  if ((size_t)(last - in) >= inflater->left) {
1716
20.8k
    last = in + inflater->left;
1717
20.8k
    fin = 1;
1718
20.8k
  }
1719
21.0k
  readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
1720
21.0k
                                   (size_t)(last - in), fin);
1721
1722
21.0k
  if (readlen < 0) {
1723
32
    DEBUGF("inflatehd: huffman decoding failed\n");
1724
32
    return readlen;
1725
32
  }
1726
21.0k
  if (nghttp2_hd_huff_decode_failure_state(&inflater->huff_decode_ctx)) {
1727
11
    DEBUGF("inflatehd: huffman decoding failed\n");
1728
11
    return NGHTTP2_ERR_HEADER_COMP;
1729
11
  }
1730
1731
21.0k
  inflater->left -= (size_t)readlen;
1732
21.0k
  return readlen;
1733
21.0k
}
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
182k
                                     const uint8_t *last) {
1750
182k
  size_t len = nghttp2_min_size((size_t)(last - in), inflater->left);
1751
1752
182k
  buf->last = nghttp2_cpymem(buf->last, in, len);
1753
1754
182k
  inflater->left -= len;
1755
182k
  return (nghttp2_ssize)len;
1756
182k
}
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
135k
                                      nghttp2_hd_nv *nv_out) {
1764
135k
  nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1765
1766
135k
  emit_header(nv_out, &nv);
1767
135k
}
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
86.6k
                                     nghttp2_hd_nv *nv_out) {
1782
86.6k
  nghttp2_hd_nv nv;
1783
86.6k
  int rv;
1784
1785
86.6k
  if (inflater->no_index) {
1786
4.51k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1787
82.1k
  } else {
1788
82.1k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1789
82.1k
  }
1790
1791
86.6k
  nv.name = inflater->namercbuf;
1792
86.6k
  nv.value = inflater->valuercbuf;
1793
86.6k
  nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
1794
1795
86.6k
  if (inflater->index_required) {
1796
10.4k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1797
1798
10.4k
    if (rv != 0) {
1799
0
      return rv;
1800
0
    }
1801
10.4k
  }
1802
1803
86.6k
  emit_header(nv_out, &nv);
1804
1805
86.6k
  inflater->nv_name_keep = nv.name;
1806
86.6k
  inflater->nv_value_keep = nv.value;
1807
1808
86.6k
  inflater->namercbuf = NULL;
1809
86.6k
  inflater->valuercbuf = NULL;
1810
1811
86.6k
  return 0;
1812
86.6k
}
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
29.9k
                                     nghttp2_hd_nv *nv_out) {
1827
29.9k
  nghttp2_hd_nv nv;
1828
29.9k
  int rv;
1829
1830
29.9k
  nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
1831
1832
29.9k
  if (inflater->no_index) {
1833
1.86k
    nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
1834
28.0k
  } else {
1835
28.0k
    nv.flags = NGHTTP2_NV_FLAG_NONE;
1836
28.0k
  }
1837
1838
29.9k
  nghttp2_rcbuf_incref(nv.name);
1839
1840
29.9k
  nv.value = inflater->valuercbuf;
1841
1842
29.9k
  if (inflater->index_required) {
1843
16.5k
    rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
1844
16.5k
    if (rv != 0) {
1845
0
      nghttp2_rcbuf_decref(nv.name);
1846
0
      return NGHTTP2_ERR_NOMEM;
1847
0
    }
1848
16.5k
  }
1849
1850
29.9k
  emit_header(nv_out, &nv);
1851
1852
29.9k
  inflater->nv_name_keep = nv.name;
1853
29.9k
  inflater->nv_value_keep = nv.value;
1854
1855
29.9k
  inflater->valuercbuf = NULL;
1856
1857
29.9k
  return 0;
1858
29.9k
}
1859
1860
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
1861
                              int *inflate_flags, uint8_t *in, size_t inlen,
1862
0
                              int in_final) {
1863
0
  return nghttp2_hd_inflate_hd2(inflater, nv_out, inflate_flags, in, inlen,
1864
0
                                in_final);
1865
0
}
1866
1867
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
1868
                               nghttp2_nv *nv_out, int *inflate_flags,
1869
0
                               const uint8_t *in, size_t inlen, int in_final) {
1870
0
  return (nghttp2_ssize)nghttp2_hd_inflate_hd3(inflater, nv_out, inflate_flags,
1871
0
                                               in, inlen, in_final);
1872
0
}
1873
1874
nghttp2_ssize nghttp2_hd_inflate_hd3(nghttp2_hd_inflater *inflater,
1875
                                     nghttp2_nv *nv_out, int *inflate_flags,
1876
                                     const uint8_t *in, size_t inlen,
1877
0
                                     int in_final) {
1878
0
  nghttp2_ssize rv;
1879
0
  nghttp2_hd_nv hd_nv;
1880
1881
0
  rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
1882
0
                                in_final);
1883
1884
0
  if (rv < 0) {
1885
0
    return rv;
1886
0
  }
1887
1888
0
  if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
1889
0
    nv_out->name = hd_nv.name->base;
1890
0
    nv_out->namelen = hd_nv.name->len;
1891
1892
0
    nv_out->value = hd_nv.value->base;
1893
0
    nv_out->valuelen = hd_nv.value->len;
1894
1895
0
    nv_out->flags = hd_nv.flags;
1896
0
  }
1897
1898
0
  return rv;
1899
0
}
1900
1901
nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
1902
                                       nghttp2_hd_nv *nv_out,
1903
                                       int *inflate_flags, const uint8_t *in,
1904
275k
                                       size_t inlen, int in_final) {
1905
275k
  nghttp2_ssize rv = 0;
1906
275k
  const uint8_t *first = in;
1907
275k
  const uint8_t *last = in + inlen;
1908
275k
  int rfin = 0;
1909
275k
  int busy = 0;
1910
275k
  nghttp2_mem *mem;
1911
1912
275k
  mem = inflater->ctx.mem;
1913
1914
275k
  if (inflater->ctx.bad) {
1915
0
    return NGHTTP2_ERR_HEADER_COMP;
1916
0
  }
1917
1918
275k
  DEBUGF("inflatehd: start state=%d\n", inflater->state);
1919
275k
  hd_inflate_keep_free(inflater);
1920
275k
  *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
1921
855k
  for (; in != last || busy;) {
1922
834k
    busy = 0;
1923
834k
    switch (inflater->state) {
1924
15
    case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
1925
15
      if ((*in & 0xe0u) != 0x20u) {
1926
2
        DEBUGF("inflatehd: header table size change was expected, but saw "
1927
2
               "0x%02x as first byte",
1928
2
               *in);
1929
2
        rv = NGHTTP2_ERR_HEADER_COMP;
1930
2
        goto fail;
1931
2
      }
1932
    /* fall through */
1933
17.3k
    case NGHTTP2_HD_STATE_INFLATE_START:
1934
256k
    case NGHTTP2_HD_STATE_OPCODE:
1935
256k
      if ((*in & 0xe0u) == 0x20u) {
1936
2.95k
        DEBUGF("inflatehd: header table size change\n");
1937
2.95k
        if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
1938
50
          DEBUGF("inflatehd: header table size change must appear at the head "
1939
50
                 "of header block\n");
1940
50
          rv = NGHTTP2_ERR_HEADER_COMP;
1941
50
          goto fail;
1942
50
        }
1943
2.90k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1944
2.90k
        inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
1945
253k
      } else if (*in & 0x80u) {
1946
135k
        DEBUGF("inflatehd: indexed repr\n");
1947
135k
        inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
1948
135k
        inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1949
135k
      } else {
1950
117k
        if (*in == 0x40u || *in == 0 || *in == 0x10u) {
1951
87.2k
          DEBUGF("inflatehd: literal header repr - new name\n");
1952
87.2k
          inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
1953
87.2k
          inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
1954
87.2k
        } else {
1955
30.5k
          DEBUGF("inflatehd: literal header repr - indexed name\n");
1956
30.5k
          inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
1957
30.5k
          inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
1958
30.5k
        }
1959
117k
        inflater->index_required = (*in & 0x40) != 0;
1960
117k
        inflater->no_index = (*in & 0xf0u) == 0x10u;
1961
117k
        DEBUGF("inflatehd: indexing required=%d, no_index=%d\n",
1962
117k
               inflater->index_required, inflater->no_index);
1963
117k
        if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
1964
87.2k
          ++in;
1965
87.2k
        }
1966
117k
      }
1967
256k
      inflater->left = 0;
1968
256k
      inflater->shift = 0;
1969
256k
      break;
1970
3.32k
    case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
1971
3.32k
      rfin = 0;
1972
3.32k
      rv = hd_inflate_read_len(
1973
3.32k
        inflater, &rfin, in, last, 5,
1974
3.32k
        nghttp2_min_size(inflater->min_hd_table_bufsize_max,
1975
3.32k
                         inflater->settings_hd_table_bufsize_max));
1976
3.32k
      if (rv < 0) {
1977
200
        goto fail;
1978
200
      }
1979
3.12k
      in += rv;
1980
3.12k
      if (!rfin) {
1981
459
        goto almost_ok;
1982
459
      }
1983
2.66k
      DEBUGF("inflatehd: table_size=%zu\n", inflater->left);
1984
2.66k
      inflater->min_hd_table_bufsize_max = UINT32_MAX;
1985
2.66k
      inflater->ctx.hd_table_bufsize_max = inflater->left;
1986
2.66k
      hd_context_shrink_table_size(&inflater->ctx, NULL);
1987
2.66k
      inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
1988
2.66k
      break;
1989
166k
    case NGHTTP2_HD_STATE_READ_INDEX: {
1990
166k
      size_t prefixlen;
1991
1992
166k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
1993
135k
        prefixlen = 7;
1994
135k
      } else if (inflater->index_required) {
1995
16.8k
        prefixlen = 6;
1996
16.8k
      } else {
1997
13.8k
        prefixlen = 4;
1998
13.8k
      }
1999
2000
166k
      rfin = 0;
2001
166k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
2002
166k
                               get_max_index(&inflater->ctx));
2003
166k
      if (rv < 0) {
2004
366
        goto fail;
2005
366
      }
2006
2007
166k
      in += rv;
2008
2009
166k
      if (!rfin) {
2010
149
        goto almost_ok;
2011
149
      }
2012
2013
165k
      if (inflater->left == 0) {
2014
13
        rv = NGHTTP2_ERR_HEADER_COMP;
2015
13
        goto fail;
2016
13
      }
2017
2018
165k
      DEBUGF("inflatehd: index=%zu\n", inflater->left);
2019
165k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
2020
135k
        inflater->index = inflater->left;
2021
135k
        --inflater->index;
2022
2023
135k
        hd_inflate_commit_indexed(inflater, nv_out);
2024
2025
135k
        inflater->state = NGHTTP2_HD_STATE_OPCODE;
2026
135k
        *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2027
135k
        return (nghttp2_ssize)(in - first);
2028
135k
      } else {
2029
30.4k
        inflater->index = inflater->left;
2030
30.4k
        --inflater->index;
2031
2032
30.4k
        inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2033
30.4k
      }
2034
30.4k
      break;
2035
165k
    }
2036
87.1k
    case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
2037
87.1k
      hd_inflate_set_huffman_encoded(inflater, in);
2038
87.1k
      inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
2039
87.1k
      inflater->left = 0;
2040
87.1k
      inflater->shift = 0;
2041
87.1k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2042
    /* Fall through */
2043
87.3k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
2044
87.3k
      rfin = 0;
2045
87.3k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2046
87.3k
      if (rv < 0) {
2047
170
        goto fail;
2048
170
      }
2049
87.1k
      in += rv;
2050
87.1k
      if (!rfin) {
2051
173
        DEBUGF("inflatehd: integer not fully decoded. current=%zu\n",
2052
173
               inflater->left);
2053
2054
173
        goto almost_ok;
2055
173
      }
2056
2057
86.9k
      if (inflater->huffman_encoded) {
2058
7.13k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2059
2060
7.13k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
2061
2062
7.13k
        rv =
2063
7.13k
          nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1, mem);
2064
79.8k
      } else {
2065
79.8k
        inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
2066
79.8k
        rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
2067
79.8k
      }
2068
2069
86.9k
      if (rv != 0) {
2070
0
        goto fail;
2071
0
      }
2072
2073
86.9k
      nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
2074
86.9k
                            inflater->namercbuf->len);
2075
2076
86.9k
      break;
2077
7.11k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
2078
7.11k
      rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
2079
7.11k
      if (rv < 0) {
2080
14
        goto fail;
2081
14
      }
2082
2083
7.10k
      in += rv;
2084
2085
7.10k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2086
2087
7.10k
      if (inflater->left) {
2088
65
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2089
2090
65
        goto almost_ok;
2091
65
      }
2092
2093
7.03k
      *inflater->namebuf.last = '\0';
2094
7.03k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2095
2096
7.03k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2097
2098
7.03k
      break;
2099
79.8k
    case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
2100
79.8k
      rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
2101
79.8k
      if (rv < 0) {
2102
0
        goto fail;
2103
0
      }
2104
2105
79.8k
      in += rv;
2106
2107
79.8k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2108
79.8k
      if (inflater->left) {
2109
137
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2110
2111
137
        goto almost_ok;
2112
137
      }
2113
2114
79.6k
      *inflater->namebuf.last = '\0';
2115
79.6k
      inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
2116
2117
79.6k
      inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
2118
2119
79.6k
      break;
2120
117k
    case NGHTTP2_HD_STATE_CHECK_VALUELEN:
2121
117k
      hd_inflate_set_huffman_encoded(inflater, in);
2122
117k
      inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
2123
117k
      inflater->left = 0;
2124
117k
      inflater->shift = 0;
2125
117k
      DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
2126
    /* Fall through */
2127
117k
    case NGHTTP2_HD_STATE_READ_VALUELEN:
2128
117k
      rfin = 0;
2129
117k
      rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
2130
117k
      if (rv < 0) {
2131
171
        goto fail;
2132
171
      }
2133
2134
117k
      in += rv;
2135
2136
117k
      if (!rfin) {
2137
201
        goto almost_ok;
2138
201
      }
2139
2140
116k
      DEBUGF("inflatehd: valuelen=%zu\n", inflater->left);
2141
2142
116k
      if (inflater->huffman_encoded) {
2143
13.9k
        nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
2144
2145
13.9k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
2146
2147
13.9k
        rv =
2148
13.9k
          nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1, mem);
2149
102k
      } else {
2150
102k
        inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
2151
2152
102k
        rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
2153
102k
      }
2154
2155
116k
      if (rv != 0) {
2156
0
        goto fail;
2157
0
      }
2158
2159
116k
      nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
2160
116k
                            inflater->valuercbuf->len);
2161
2162
116k
      busy = 1;
2163
2164
116k
      break;
2165
13.9k
    case NGHTTP2_HD_STATE_READ_VALUEHUFF:
2166
13.9k
      rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
2167
13.9k
      if (rv < 0) {
2168
29
        goto fail;
2169
29
      }
2170
2171
13.9k
      in += rv;
2172
2173
13.9k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2174
2175
13.9k
      if (inflater->left) {
2176
98
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2177
2178
98
        goto almost_ok;
2179
98
      }
2180
2181
13.8k
      *inflater->valuebuf.last = '\0';
2182
13.8k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2183
2184
13.8k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2185
7.01k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2186
7.01k
      } else {
2187
6.80k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2188
6.80k
      }
2189
2190
13.8k
      if (rv != 0) {
2191
0
        goto fail;
2192
0
      }
2193
2194
13.8k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2195
13.8k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2196
2197
13.8k
      return (nghttp2_ssize)(in - first);
2198
102k
    case NGHTTP2_HD_STATE_READ_VALUE:
2199
102k
      rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
2200
102k
      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
102k
      in += rv;
2207
2208
102k
      DEBUGF("inflatehd: %td bytes read\n", rv);
2209
2210
102k
      if (inflater->left) {
2211
202
        DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
2212
202
        goto almost_ok;
2213
202
      }
2214
2215
102k
      *inflater->valuebuf.last = '\0';
2216
102k
      inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
2217
2218
102k
      if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
2219
79.6k
        rv = hd_inflate_commit_newname(inflater, nv_out);
2220
79.6k
      } else {
2221
23.1k
        rv = hd_inflate_commit_indname(inflater, nv_out);
2222
23.1k
      }
2223
2224
102k
      if (rv != 0) {
2225
0
        goto fail;
2226
0
      }
2227
2228
102k
      inflater->state = NGHTTP2_HD_STATE_OPCODE;
2229
102k
      *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
2230
2231
102k
      return (nghttp2_ssize)(in - first);
2232
834k
    }
2233
834k
  }
2234
2235
275k
  assert(in == last);
2236
2237
20.8k
  DEBUGF("inflatehd: all input bytes were processed\n");
2238
2239
20.8k
  if (in_final) {
2240
14.5k
    DEBUGF("inflatehd: in_final set\n");
2241
2242
14.5k
    if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
2243
8.23k
        inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
2244
10
      DEBUGF("inflatehd: unacceptable state=%d\n", inflater->state);
2245
10
      rv = NGHTTP2_ERR_HEADER_COMP;
2246
2247
10
      goto fail;
2248
10
    }
2249
14.5k
    *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
2250
14.5k
  }
2251
20.8k
  return (nghttp2_ssize)(in - first);
2252
2253
1.48k
almost_ok:
2254
1.48k
  if (in_final) {
2255
10
    DEBUGF("inflatehd: input ended prematurely\n");
2256
2257
10
    rv = NGHTTP2_ERR_HEADER_COMP;
2258
2259
10
    goto fail;
2260
10
  }
2261
1.47k
  return (nghttp2_ssize)(in - first);
2262
2263
1.03k
fail:
2264
1.03k
  DEBUGF("inflatehd: error return %td\n", rv);
2265
2266
1.03k
  inflater->ctx.bad = 1;
2267
1.03k
  return rv;
2268
1.48k
}
2269
2270
14.5k
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
2271
14.5k
  hd_inflate_keep_free(inflater);
2272
14.5k
  inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
2273
14.5k
  return 0;
2274
14.5k
}
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
}