Coverage Report

Created: 2025-12-14 06:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/nghttp2/tests/nghttp2_test_helper.c
Line
Count
Source
1
/*
2
 * nghttp2 - HTTP/2 C Library
3
 *
4
 * Copyright (c) 2012 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_test_helper.h"
26
27
#include <stdio.h>
28
#include <assert.h>
29
30
#include "nghttp2_helper.h"
31
#include "nghttp2_priority_spec.h"
32
33
4.49k
int unpack_framebuf(nghttp2_frame *frame, nghttp2_bufs *bufs) {
34
4.49k
  nghttp2_buf *buf;
35
36
  /* Assuming we have required data in first buffer. We don't decode
37
     header block so, we don't mind its space */
38
4.49k
  buf = &bufs->head->buf;
39
4.49k
  return unpack_frame(frame, buf->pos, nghttp2_buf_len(buf));
40
4.49k
}
41
42
4.49k
int unpack_frame(nghttp2_frame *frame, const uint8_t *in, size_t len) {
43
4.49k
  int rv = 0;
44
4.49k
  const uint8_t *payload = in + NGHTTP2_FRAME_HDLEN;
45
4.49k
  size_t payloadlen = len - NGHTTP2_FRAME_HDLEN;
46
4.49k
  size_t payloadoff;
47
4.49k
  nghttp2_mem *mem;
48
49
4.49k
  mem = nghttp2_mem_default();
50
51
4.49k
  nghttp2_frame_unpack_frame_hd(&frame->hd, in);
52
4.49k
  switch (frame->hd.type) {
53
2.24k
  case NGHTTP2_HEADERS:
54
2.24k
    payloadoff = ((frame->hd.flags & NGHTTP2_FLAG_PADDED) > 0);
55
2.24k
    nghttp2_frame_unpack_headers_payload(&frame->headers, payload + payloadoff);
56
2.24k
    break;
57
0
  case NGHTTP2_PRIORITY:
58
0
    nghttp2_frame_unpack_priority_payload(&frame->priority, payload);
59
0
    break;
60
0
  case NGHTTP2_RST_STREAM:
61
0
    nghttp2_frame_unpack_rst_stream_payload(&frame->rst_stream, payload);
62
0
    break;
63
0
  case NGHTTP2_SETTINGS:
64
0
    rv = nghttp2_frame_unpack_settings_payload2(
65
0
      &frame->settings.iv, &frame->settings.niv, payload, payloadlen, mem);
66
0
    break;
67
2.24k
  case NGHTTP2_PUSH_PROMISE:
68
2.24k
    nghttp2_frame_unpack_push_promise_payload(&frame->push_promise, payload);
69
2.24k
    break;
70
0
  case NGHTTP2_PING:
71
0
    nghttp2_frame_unpack_ping_payload(&frame->ping, payload);
72
0
    break;
73
0
  case NGHTTP2_GOAWAY:
74
0
    nghttp2_frame_unpack_goaway_payload2(&frame->goaway, payload, payloadlen,
75
0
                                         mem);
76
0
    break;
77
0
  case NGHTTP2_WINDOW_UPDATE:
78
0
    nghttp2_frame_unpack_window_update_payload(&frame->window_update, payload);
79
0
    break;
80
0
  case NGHTTP2_ALTSVC:
81
0
    assert(payloadlen > 2);
82
0
    nghttp2_frame_unpack_altsvc_payload2(&frame->ext, payload, payloadlen, mem);
83
0
    break;
84
0
  case NGHTTP2_ORIGIN:
85
0
    rv = nghttp2_frame_unpack_origin_payload(&frame->ext, payload, payloadlen,
86
0
                                             mem);
87
0
    break;
88
0
  case NGHTTP2_PRIORITY_UPDATE:
89
0
    assert(payloadlen >= 4);
90
0
    nghttp2_frame_unpack_priority_update_payload(
91
0
      &frame->ext, (uint8_t *)payload, payloadlen);
92
0
    break;
93
0
  default:
94
    /* Must not be reachable */
95
0
    assert(0);
96
4.49k
  }
97
4.49k
  return rv;
98
4.49k
}
99
100
0
int strmemeq(const char *a, const uint8_t *b, size_t bn) {
101
0
  const uint8_t *c;
102
0
  if (!a || !b) {
103
0
    return 0;
104
0
  }
105
0
  c = b + bn;
106
0
  for (; *a && b != c && *a == *b; ++a, ++b)
107
0
    ;
108
0
  return !*a && b == c;
109
0
}
110
111
0
int nvnameeq(const char *a, nghttp2_nv *nv) {
112
0
  return strmemeq(a, nv->name, nv->namelen);
113
0
}
114
115
0
int nvvalueeq(const char *a, nghttp2_nv *nv) {
116
0
  return strmemeq(a, nv->value, nv->valuelen);
117
0
}
118
119
4.49k
void nva_out_init(nva_out *out) {
120
4.49k
  memset(out->nva, 0, sizeof(out->nva));
121
4.49k
  out->nvlen = 0;
122
4.49k
}
123
124
2.24k
void nva_out_reset(nva_out *out, nghttp2_mem *mem) {
125
2.24k
  size_t i;
126
17.9k
  for (i = 0; i < out->nvlen; ++i) {
127
15.7k
    mem->free(out->nva[i].name, NULL);
128
15.7k
    mem->free(out->nva[i].value, NULL);
129
15.7k
  }
130
2.24k
  memset(out->nva, 0, sizeof(out->nva));
131
2.24k
  out->nvlen = 0;
132
2.24k
}
133
134
15.7k
void add_out(nva_out *out, nghttp2_nv *nv, nghttp2_mem *mem) {
135
15.7k
  nghttp2_nv *onv = &out->nva[out->nvlen];
136
15.7k
  if (nv->namelen) {
137
4.42k
    onv->name = mem->malloc(nv->namelen, NULL);
138
4.42k
    memcpy(onv->name, nv->name, nv->namelen);
139
11.3k
  } else {
140
11.3k
    onv->name = NULL;
141
11.3k
  }
142
15.7k
  if (nv->valuelen) {
143
1.32k
    onv->value = mem->malloc(nv->valuelen, NULL);
144
1.32k
    memcpy(onv->value, nv->value, nv->valuelen);
145
14.4k
  } else {
146
14.4k
    onv->value = NULL;
147
14.4k
  }
148
15.7k
  onv->namelen = nv->namelen;
149
15.7k
  onv->valuelen = nv->valuelen;
150
151
15.7k
  onv->flags = nv->flags;
152
153
15.7k
  ++out->nvlen;
154
15.7k
}
155
156
nghttp2_ssize inflate_hd(nghttp2_hd_inflater *inflater, nva_out *out,
157
2.24k
                         nghttp2_bufs *bufs, size_t offset, nghttp2_mem *mem) {
158
2.24k
  nghttp2_ssize rv;
159
2.24k
  nghttp2_nv nv;
160
2.24k
  int inflate_flags;
161
2.24k
  nghttp2_buf_chain *ci;
162
2.24k
  nghttp2_buf *buf;
163
2.24k
  nghttp2_buf bp;
164
2.24k
  int fin;
165
2.24k
  size_t processed;
166
167
2.24k
  processed = 0;
168
169
4.49k
  for (ci = bufs->head; ci; ci = ci->next) {
170
2.24k
    buf = &ci->buf;
171
2.24k
    fin = nghttp2_buf_len(buf) == 0 || ci->next == NULL;
172
2.24k
    bp = *buf;
173
174
2.24k
    if (offset) {
175
2.24k
      size_t n;
176
177
2.24k
      n = nghttp2_min_size(offset, nghttp2_buf_len(&bp));
178
2.24k
      bp.pos += n;
179
2.24k
      offset -= n;
180
2.24k
    }
181
182
17.9k
    for (;;) {
183
17.9k
      inflate_flags = 0;
184
17.9k
      rv = nghttp2_hd_inflate_hd3(inflater, &nv, &inflate_flags, bp.pos,
185
17.9k
                                  nghttp2_buf_len(&bp), fin);
186
187
17.9k
      if (rv < 0) {
188
0
        return rv;
189
0
      }
190
191
17.9k
      bp.pos += rv;
192
17.9k
      processed += (size_t)rv;
193
194
17.9k
      if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
195
15.7k
        if (out) {
196
15.7k
          add_out(out, &nv, mem);
197
15.7k
        }
198
15.7k
      }
199
17.9k
      if (inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
200
2.24k
        break;
201
2.24k
      }
202
15.7k
      if ((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 &&
203
0
          nghttp2_buf_len(&bp) == 0) {
204
0
        break;
205
0
      }
206
15.7k
    }
207
2.24k
  }
208
209
2.24k
  nghttp2_hd_inflate_end_headers(inflater);
210
211
2.24k
  return (nghttp2_ssize)processed;
212
2.24k
}
213
214
int pack_headers(nghttp2_bufs *bufs, nghttp2_hd_deflater *deflater,
215
                 int32_t stream_id, uint8_t flags, const nghttp2_nv *nva,
216
0
                 size_t nvlen, nghttp2_mem *mem) {
217
0
  nghttp2_nv *dnva;
218
0
  nghttp2_frame frame;
219
0
  int rv;
220
221
0
  nghttp2_nv_array_copy(&dnva, nva, nvlen, mem);
222
223
0
  nghttp2_frame_headers_init(&frame.headers, flags, stream_id,
224
0
                             NGHTTP2_HCAT_HEADERS, NULL, dnva, nvlen);
225
0
  rv = nghttp2_frame_pack_headers(bufs, &frame.headers, deflater);
226
227
0
  nghttp2_frame_headers_free(&frame.headers, mem);
228
229
0
  return rv;
230
0
}
231
232
int pack_push_promise(nghttp2_bufs *bufs, nghttp2_hd_deflater *deflater,
233
                      int32_t stream_id, uint8_t flags,
234
                      int32_t promised_stream_id, const nghttp2_nv *nva,
235
0
                      size_t nvlen, nghttp2_mem *mem) {
236
0
  nghttp2_nv *dnva;
237
0
  nghttp2_frame frame;
238
0
  int rv;
239
240
0
  nghttp2_nv_array_copy(&dnva, nva, nvlen, mem);
241
242
0
  nghttp2_frame_push_promise_init(&frame.push_promise, flags, stream_id,
243
0
                                  promised_stream_id, dnva, nvlen);
244
0
  rv = nghttp2_frame_pack_push_promise(bufs, &frame.push_promise, deflater);
245
246
0
  nghttp2_frame_push_promise_free(&frame.push_promise, mem);
247
248
0
  return rv;
249
0
}
250
251
4.49k
int frame_pack_bufs_init(nghttp2_bufs *bufs) {
252
  /* 1 for Pad Length */
253
4.49k
  return nghttp2_bufs_init2(bufs, 4096, 16, NGHTTP2_FRAME_HDLEN + 1,
254
4.49k
                            nghttp2_mem_default());
255
4.49k
}
256
257
0
void bufs_large_init(nghttp2_bufs *bufs, size_t chunk_size) {
258
  /* 1 for Pad Length */
259
0
  nghttp2_bufs_init2(bufs, chunk_size, 16, NGHTTP2_FRAME_HDLEN + 1,
260
0
                     nghttp2_mem_default());
261
0
}
262
263
0
nghttp2_stream *open_stream(nghttp2_session *session, int32_t stream_id) {
264
0
  return nghttp2_session_open_stream(
265
0
    session, stream_id, NGHTTP2_STREAM_FLAG_NONE, NGHTTP2_STREAM_OPENED, NULL);
266
0
}
267
268
0
nghttp2_outbound_item *create_data_ob_item(nghttp2_mem *mem) {
269
0
  nghttp2_outbound_item *item;
270
271
0
  item = mem->malloc(sizeof(nghttp2_outbound_item), NULL);
272
0
  memset(item, 0, sizeof(nghttp2_outbound_item));
273
274
0
  return item;
275
0
}
276
277
0
nghttp2_stream *open_sent_stream(nghttp2_session *session, int32_t stream_id) {
278
0
  return open_sent_stream3(session, stream_id, NGHTTP2_FLAG_NONE,
279
0
                           NGHTTP2_STREAM_OPENED, NULL);
280
0
}
281
282
nghttp2_stream *open_sent_stream2(nghttp2_session *session, int32_t stream_id,
283
0
                                  nghttp2_stream_state initial_state) {
284
0
  return open_sent_stream3(session, stream_id, NGHTTP2_FLAG_NONE, initial_state,
285
0
                           NULL);
286
0
}
287
288
nghttp2_stream *open_sent_stream3(nghttp2_session *session, int32_t stream_id,
289
                                  uint8_t flags,
290
                                  nghttp2_stream_state initial_state,
291
0
                                  void *stream_user_data) {
292
0
  nghttp2_stream *stream;
293
294
0
  assert(nghttp2_session_is_my_stream_id(session, stream_id));
295
296
0
  stream = nghttp2_session_open_stream(session, stream_id, flags, initial_state,
297
0
                                       stream_user_data);
298
0
  session->last_sent_stream_id =
299
0
    nghttp2_max_int32(session->last_sent_stream_id, stream_id);
300
0
  session->next_stream_id =
301
0
    nghttp2_max_uint32(session->next_stream_id, (uint32_t)stream_id + 2);
302
303
0
  return stream;
304
0
}
305
306
0
nghttp2_stream *open_recv_stream(nghttp2_session *session, int32_t stream_id) {
307
0
  return open_recv_stream3(session, stream_id, NGHTTP2_FLAG_NONE,
308
0
                           NGHTTP2_STREAM_OPENED, NULL);
309
0
}
310
311
nghttp2_stream *open_recv_stream2(nghttp2_session *session, int32_t stream_id,
312
0
                                  nghttp2_stream_state initial_state) {
313
0
  return open_recv_stream3(session, stream_id, NGHTTP2_FLAG_NONE, initial_state,
314
0
                           NULL);
315
0
}
316
317
nghttp2_stream *open_recv_stream3(nghttp2_session *session, int32_t stream_id,
318
                                  uint8_t flags,
319
                                  nghttp2_stream_state initial_state,
320
0
                                  void *stream_user_data) {
321
0
  nghttp2_stream *stream;
322
323
0
  assert(!nghttp2_session_is_my_stream_id(session, stream_id));
324
325
0
  stream = nghttp2_session_open_stream(session, stream_id, flags, initial_state,
326
0
                                       stream_user_data);
327
0
  session->last_recv_stream_id =
328
0
    nghttp2_max_int32(session->last_recv_stream_id, stream_id);
329
330
0
  return stream;
331
0
}