1 /*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License").
5 * You may not use this file except in compliance with the License.
6 * A copy of the License is located at
7 *
8 * http://aws.amazon.com/apache2.0
9 *
10 * or in the "license" file accompanying this file. This file is distributed
11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 * express or implied. See the License for the specific language governing
13 * permissions and limitations under the License.
14 */
15
16 #include "s2n_test.h"
17 #include <string.h>
18
19 #include "stuffer/s2n_stuffer.h"
20 #include "utils/s2n_blob.h"
21 #include "utils/s2n_random.h"
22
main(int argc,char ** argv)23 int main(int argc, char **argv)
24 {
25 char c;
26 uint32_t skipped = 0;
27 struct s2n_stuffer stuffer, token;
28 struct s2n_blob pad_blob, token_blob;
29 char text[] = " This is some text\r\n\tmore text";
30 char fields[] = "one,two,three";
31 uint8_t pad[1024];
32 char out[1024];
33 char tokenpad[6];
34
35 BEGIN_TEST();
36 EXPECT_SUCCESS(s2n_disable_tls13());
37
38 /* Check whitespace reading */
39 {
40 /* Create a stuffer */
41 EXPECT_SUCCESS(s2n_blob_init(&token_blob, (uint8_t *)tokenpad, sizeof(tokenpad)));
42 EXPECT_SUCCESS(s2n_stuffer_init(&token, &token_blob));
43 EXPECT_SUCCESS(s2n_blob_init(&pad_blob, (uint8_t *)pad, sizeof(pad)));
44 EXPECT_SUCCESS(s2n_stuffer_init(&stuffer, &pad_blob));
45 EXPECT_SUCCESS(s2n_stuffer_write_text(&stuffer, text, sizeof(text)));
46
47 /* Skip 4 bytes of whitespace */
48 EXPECT_SUCCESS(s2n_stuffer_skip_whitespace(&stuffer, &skipped));
49 EXPECT_EQUAL(skipped, 4);
50 EXPECT_SUCCESS(s2n_stuffer_peek_char(&stuffer, &c));
51 EXPECT_EQUAL(c, 'T');
52
53 /* Read the next 17 chars */
54 EXPECT_SUCCESS(s2n_stuffer_read_text(&stuffer, out, 17));
55 EXPECT_EQUAL(memcmp(out, "This is some text", 17), 0);
56
57 /* Skip 3 bytes of whitespace */
58 EXPECT_SUCCESS(s2n_stuffer_skip_whitespace(&stuffer, &skipped));
59 EXPECT_EQUAL(skipped, 3);
60
61 /* Read the next 10 chars (including the terminating zero) */
62 EXPECT_SUCCESS(s2n_stuffer_read_text(&stuffer, out, 10));
63 EXPECT_EQUAL(memcmp(out, "more text", 10), 0);
64
65 /* Test end of stream behaviour */
66 EXPECT_SUCCESS(s2n_stuffer_skip_whitespace(&stuffer, NULL));
67 EXPECT_FAILURE(s2n_stuffer_peek_char(&stuffer, &c));
68 EXPECT_FAILURE(s2n_stuffer_read_char(&stuffer, &c));
69 }
70
71 /* Check read_until, rewinding, and expecting */
72 {
73 /* Create a stuffer */
74 EXPECT_SUCCESS(s2n_blob_init(&token_blob, (uint8_t *)tokenpad, sizeof(tokenpad)));
75 EXPECT_SUCCESS(s2n_stuffer_init(&token, &token_blob));
76 EXPECT_SUCCESS(s2n_blob_init(&pad_blob, (uint8_t *)pad, sizeof(pad)));
77 EXPECT_SUCCESS(s2n_stuffer_init(&stuffer, &pad_blob));
78 EXPECT_SUCCESS(s2n_stuffer_write_text(&stuffer, text, sizeof(text)));
79
80 char target[] = "text";
81 char non_target[] = "someStringNotInStuffer";
82 EXPECT_SUCCESS(s2n_stuffer_skip_read_until(&stuffer, target));
83 EXPECT_EQUAL(stuffer.read_cursor, 21);
84 EXPECT_SUCCESS(s2n_stuffer_rewind_read(&stuffer, strlen(target)));
85 EXPECT_EQUAL(stuffer.read_cursor, 17);
86 EXPECT_SUCCESS(s2n_stuffer_read_expected_str(&stuffer, target));
87 EXPECT_EQUAL(stuffer.read_cursor, 21);
88 EXPECT_SUCCESS(s2n_stuffer_skip_read_until(&stuffer, target));
89 EXPECT_EQUAL(stuffer.read_cursor, 33);
90 EXPECT_FAILURE(s2n_stuffer_rewind_read(&stuffer, 99));
91 EXPECT_SUCCESS(s2n_stuffer_reread(&stuffer));
92 EXPECT_SUCCESS(s2n_stuffer_skip_read_until(&stuffer, non_target));
93 EXPECT_EQUAL(stuffer.read_cursor, stuffer.write_cursor - strlen(non_target) + 1);
94 }
95
96 /* Check token reading */
97 {
98 /* Start a new buffer */
99 EXPECT_SUCCESS(s2n_stuffer_init(&stuffer, &pad_blob));
100 EXPECT_SUCCESS(s2n_stuffer_write_text(&stuffer, fields, strlen(fields)));
101
102 EXPECT_SUCCESS(s2n_stuffer_read_token(&stuffer, &token, ','));
103 EXPECT_EQUAL(memcmp("one", token.blob.data, 3), 0);
104
105 EXPECT_SUCCESS(s2n_stuffer_init(&token, &token_blob));
106 EXPECT_SUCCESS(s2n_stuffer_read_token(&stuffer, &token, ','));
107 EXPECT_EQUAL(memcmp("two", token.blob.data, 3), 0);
108
109 /* Check for end-of-stream termination */
110 EXPECT_SUCCESS(s2n_stuffer_init(&token, &token_blob));
111 EXPECT_SUCCESS(s2n_stuffer_read_token(&stuffer, &token, ','));
112 EXPECT_EQUAL(memcmp("three", token.blob.data, 5), 0);
113 }
114
115 /* Check line reading */
116 {
117 struct s2n_blob line_blob = { 0 };
118 struct s2n_stuffer lstuffer;
119 char lf_line[] = "a LF terminated line\n";
120 char crlf_line[] = "a CRLF terminated line\r\n";
121 char lf_line_trailing_cr[] = "a LF terminated line with trailing CR\n\r\r\r\r\r\r";
122 char not_a_line[] = "not a line";
123
124 EXPECT_SUCCESS(s2n_blob_init(&line_blob, (uint8_t *) lf_line, sizeof(lf_line)));
125 EXPECT_SUCCESS(s2n_stuffer_init(&lstuffer, &line_blob));
126 EXPECT_SUCCESS(s2n_stuffer_write(&lstuffer, &line_blob));
127 memset(pad, 0, sizeof(pad));
128 EXPECT_SUCCESS(s2n_blob_init(&pad_blob, pad, sizeof(pad)));
129 EXPECT_SUCCESS(s2n_stuffer_init(&token, &pad_blob));
130 EXPECT_SUCCESS(s2n_stuffer_read_line(&lstuffer, &token));
131 EXPECT_EQUAL(strlen("a LF terminated line"), s2n_stuffer_data_available(&token));
132 EXPECT_SUCCESS(memcmp("a LF terminated line", token.blob.data, s2n_stuffer_data_available(&token)));
133
134 EXPECT_SUCCESS(s2n_blob_init(&line_blob, (uint8_t *) crlf_line, sizeof(crlf_line)));
135 EXPECT_SUCCESS(s2n_stuffer_init(&lstuffer, &line_blob));
136 EXPECT_SUCCESS(s2n_stuffer_write(&lstuffer, &line_blob));
137 memset(pad, 0, sizeof(pad));
138 EXPECT_SUCCESS(s2n_blob_init(&pad_blob, pad, sizeof(pad)));
139 EXPECT_SUCCESS(s2n_stuffer_init(&token, &pad_blob));
140 EXPECT_SUCCESS(s2n_stuffer_read_line(&lstuffer, &token));
141 EXPECT_EQUAL(strlen("a CRLF terminated line"), s2n_stuffer_data_available(&token));
142 EXPECT_SUCCESS(memcmp("a CRLF terminated line", token.blob.data, s2n_stuffer_data_available(&token)));
143
144 EXPECT_SUCCESS(s2n_blob_init(&line_blob, (uint8_t *) lf_line_trailing_cr, sizeof(lf_line_trailing_cr)));
145 EXPECT_SUCCESS(s2n_stuffer_init(&lstuffer, &line_blob));
146 EXPECT_SUCCESS(s2n_stuffer_write(&lstuffer, &line_blob));
147 memset(pad, 0, sizeof(pad));
148 EXPECT_SUCCESS(s2n_blob_init(&pad_blob, pad, sizeof(pad)));
149 EXPECT_SUCCESS(s2n_stuffer_init(&token, &pad_blob));
150 EXPECT_SUCCESS(s2n_stuffer_read_line(&lstuffer, &token));
151 EXPECT_EQUAL(strlen("a LF terminated line with trailing CR"), s2n_stuffer_data_available(&token));
152 EXPECT_SUCCESS(memcmp("a LF terminated line with trailing CR", token.blob.data, s2n_stuffer_data_available(&token)));
153
154 EXPECT_SUCCESS(s2n_blob_init(&line_blob, (uint8_t *) not_a_line, sizeof(not_a_line)));
155 EXPECT_SUCCESS(s2n_stuffer_init(&lstuffer, &line_blob));
156 EXPECT_SUCCESS(s2n_stuffer_write(&lstuffer, &line_blob));
157 memset(pad, 0, sizeof(pad));
158 EXPECT_SUCCESS(s2n_blob_init(&pad_blob, pad, sizeof(pad)));
159 EXPECT_SUCCESS(s2n_stuffer_init(&token, &pad_blob));
160 EXPECT_SUCCESS(s2n_stuffer_read_line(&lstuffer, &token));
161 EXPECT_EQUAL(sizeof(not_a_line), s2n_stuffer_data_available(&token));
162 EXPECT_SUCCESS(memcmp("not a line", token.blob.data, s2n_stuffer_data_available(&token)));
163 }
164
165 END_TEST();
166 return 0;
167 }
168