Coverage Report

Created: 2024-05-21 06:52

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