Coverage Report

Created: 2022-11-30 06:20

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