Coverage Report

Created: 2026-01-17 06:08

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