File Coverage

reader.c
Criterion Covered Total %
statement 121 167 72.4
branch 99 158 62.6
condition n/a
subroutine n/a
pod n/a
total 220 325 67.6


line stmt bran cond sub pod time code
1              
2             #include "yaml_private.h"
3              
4             /*
5             * Declarations.
6             */
7              
8             static int
9             yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
10             size_t offset, int value);
11              
12             static int
13             yaml_parser_update_raw_buffer(yaml_parser_t *parser);
14              
15             static int
16             yaml_parser_determine_encoding(yaml_parser_t *parser);
17              
18             /*
19             * Set the reader error and return 0.
20             */
21              
22             static int
23 4           yaml_parser_set_reader_error(yaml_parser_t *parser, const char *problem,
24             size_t offset, int value)
25             {
26 4           parser->error = YAML_READER_ERROR;
27 4           parser->problem = problem;
28 4           parser->problem_offset = offset;
29 4           parser->problem_value = value;
30              
31 4           return 0;
32             }
33              
34             /*
35             * Byte order marks.
36             */
37              
38             #define BOM_UTF8 "\xef\xbb\xbf"
39             #define BOM_UTF16LE "\xff\xfe"
40             #define BOM_UTF16BE "\xfe\xff"
41              
42             /*
43             * Determine the input stream encoding by checking the BOM symbol. If no BOM is
44             * found, the UTF-8 encoding is assumed. Return 1 on success, 0 on failure.
45             */
46              
47             static int
48 109           yaml_parser_determine_encoding(yaml_parser_t *parser)
49             {
50             /* Ensure that we had enough bytes in the raw buffer. */
51              
52 218 100         while (!parser->eof
53 216 100         && parser->raw_buffer.last - parser->raw_buffer.pointer < 3) {
54 109 50         if (!yaml_parser_update_raw_buffer(parser)) {
55 0           return 0;
56             }
57             }
58              
59             /* Determine the encoding. */
60              
61 109 100         if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 2
62 107 100         && !memcmp(parser->raw_buffer.pointer, BOM_UTF16LE, 2)) {
63 1           parser->encoding = YAML_UTF16LE_ENCODING;
64 1           parser->raw_buffer.pointer += 2;
65 1           parser->offset += 2;
66             }
67 108 100         else if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 2
68 106 100         && !memcmp(parser->raw_buffer.pointer, BOM_UTF16BE, 2)) {
69 1           parser->encoding = YAML_UTF16BE_ENCODING;
70 1           parser->raw_buffer.pointer += 2;
71 1           parser->offset += 2;
72             }
73 107 100         else if (parser->raw_buffer.last - parser->raw_buffer.pointer >= 3
74 105 50         && !memcmp(parser->raw_buffer.pointer, BOM_UTF8, 3)) {
75 0           parser->encoding = YAML_UTF8_ENCODING;
76 0           parser->raw_buffer.pointer += 3;
77 0           parser->offset += 3;
78             }
79             else {
80 107           parser->encoding = YAML_UTF8_ENCODING;
81             }
82              
83 109           return 1;
84             }
85              
86             /*
87             * Update the raw buffer.
88             */
89              
90             static int
91 213           yaml_parser_update_raw_buffer(yaml_parser_t *parser)
92             {
93 213           size_t size_read = 0;
94              
95             /* Return if the raw buffer is full. */
96              
97 213 100         if (parser->raw_buffer.start == parser->raw_buffer.pointer
98 111 50         && parser->raw_buffer.last == parser->raw_buffer.end)
99 0           return 1;
100              
101             /* Return on EOF. */
102              
103 213 100         if (parser->eof)
104 2           return 1;
105              
106             /* Move the remaining bytes in the raw buffer to the beginning. */
107              
108 211 100         if (parser->raw_buffer.start < parser->raw_buffer.pointer
109 102 50         && parser->raw_buffer.pointer < parser->raw_buffer.last) {
110 0           memmove(parser->raw_buffer.start, parser->raw_buffer.pointer,
111 0           parser->raw_buffer.last - parser->raw_buffer.pointer);
112             }
113 422           parser->raw_buffer.last -=
114 211           parser->raw_buffer.pointer - parser->raw_buffer.start;
115 211           parser->raw_buffer.pointer = parser->raw_buffer.start;
116              
117             /* Call the read handler to fill the buffer. */
118              
119 211 50         if (!parser->read_handler(parser->read_handler_data, parser->raw_buffer.last,
120 211           parser->raw_buffer.end - parser->raw_buffer.last, &size_read)) {
121 0           return yaml_parser_set_reader_error(parser, "input error",
122             parser->offset, -1);
123             }
124 211           parser->raw_buffer.last += size_read;
125 211 100         if (!size_read) {
126 104           parser->eof = 1;
127             }
128              
129 213           return 1;
130             }
131              
132             /*
133             * Ensure that the buffer contains at least `length` characters.
134             * Return 1 on success, 0 on failure.
135             *
136             * The length is supposed to be significantly less that the buffer size.
137             */
138              
139             YAML_DECLARE(int)
140 354           yaml_parser_update_buffer(yaml_parser_t *parser, size_t length)
141             {
142 354           int first = 1;
143              
144 354 50         assert(parser->read_handler); /* Read handler must be set. */
145              
146             /* If the EOF flag is set and the raw buffer is empty, do nothing. */
147              
148 354 100         if (parser->eof && parser->raw_buffer.pointer == parser->raw_buffer.last)
    50          
149 143           return 1;
150              
151             /* Return if the buffer contains enough characters. */
152              
153 211 50         if (parser->unread >= length)
154 0           return 1;
155              
156             /* Determine the input encoding if it is not known yet. */
157              
158 211 100         if (!parser->encoding) {
159 109 50         if (!yaml_parser_determine_encoding(parser))
160 0           return 0;
161             }
162              
163             /* Move the unread characters to the beginning of the buffer. */
164              
165 211 100         if (parser->buffer.start < parser->buffer.pointer
166 102 50         && parser->buffer.pointer < parser->buffer.last) {
167 102           size_t size = parser->buffer.last - parser->buffer.pointer;
168 102           memmove(parser->buffer.start, parser->buffer.pointer, size);
169 102           parser->buffer.pointer = parser->buffer.start;
170 102           parser->buffer.last = parser->buffer.start + size;
171             }
172 109 50         else if (parser->buffer.pointer == parser->buffer.last) {
173 109           parser->buffer.pointer = parser->buffer.start;
174 109           parser->buffer.last = parser->buffer.start;
175             }
176              
177             /* Fill the buffer until it has enough characters. */
178              
179 317 100         while (parser->unread < length)
180             {
181             /* Fill the raw buffer if necessary. */
182              
183 211 50         if (!first || parser->raw_buffer.pointer == parser->raw_buffer.last) {
    100          
184 104 50         if (!yaml_parser_update_raw_buffer(parser))
185 0           return 0;
186             }
187 211           first = 0;
188              
189             /* Decode the raw buffer. */
190              
191 4923 100         while (parser->raw_buffer.pointer != parser->raw_buffer.last)
192             {
193 4713           unsigned int value = 0, value2 = 0;
194 4713           int incomplete = 0;
195             unsigned char octet;
196 4713           unsigned int width = 0;
197             int low, high;
198             size_t k;
199 4713           size_t raw_unread = parser->raw_buffer.last - parser->raw_buffer.pointer;
200              
201             /* Decode the next character. */
202              
203 4713           switch (parser->encoding)
204             {
205             case YAML_UTF8_ENCODING:
206              
207             /*
208             * Decode a UTF-8 character. Check RFC 3629
209             * (http://www.ietf.org/rfc/rfc3629.txt) for more details.
210             *
211             * The following table (taken from the RFC) is used for
212             * decoding.
213             *
214             * Char. number range | UTF-8 octet sequence
215             * (hexadecimal) | (binary)
216             * --------------------+------------------------------------
217             * 0000 0000-0000 007F | 0xxxxxxx
218             * 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
219             * 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
220             * 0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
221             *
222             * Additionally, the characters in the range 0xD800-0xDFFF
223             * are prohibited as they are reserved for use with UTF-16
224             * surrogate pairs.
225             */
226              
227             /* Determine the length of the UTF-8 sequence. */
228              
229 4701           octet = parser->raw_buffer.pointer[0];
230 4701 100         width = (octet & 0x80) == 0x00 ? 1 :
    100          
    50          
    0          
231 67           (octet & 0xE0) == 0xC0 ? 2 :
232 57           (octet & 0xF0) == 0xE0 ? 3 :
233 0           (octet & 0xF8) == 0xF0 ? 4 : 0;
234              
235             /* Check if the leading octet is valid. */
236              
237 4701 50         if (!width)
238 0           return yaml_parser_set_reader_error(parser,
239             "invalid leading UTF-8 octet",
240             parser->offset, octet);
241              
242             /* Check if the raw buffer contains an incomplete character. */
243              
244 4701 50         if (width > raw_unread) {
245 0 0         if (parser->eof) {
246 0           return yaml_parser_set_reader_error(parser,
247             "incomplete UTF-8 octet sequence",
248             parser->offset, -1);
249             }
250 0           incomplete = 1;
251 0           break;
252             }
253              
254             /* Decode the leading octet. */
255              
256 4701 100         value = (octet & 0x80) == 0x00 ? octet & 0x7F :
    100          
    50          
    0          
257 67           (octet & 0xE0) == 0xC0 ? octet & 0x1F :
258 57           (octet & 0xF0) == 0xE0 ? octet & 0x0F :
259 0           (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
260              
261             /* Check and decode the trailing octets. */
262              
263 4825 100         for (k = 1; k < width; k ++)
264             {
265 124           octet = parser->raw_buffer.pointer[k];
266              
267             /* Check if the octet is valid. */
268              
269 124 50         if ((octet & 0xC0) != 0x80)
270 0           return yaml_parser_set_reader_error(parser,
271             "invalid trailing UTF-8 octet",
272 0           parser->offset+k, octet);
273              
274             /* Decode the octet. */
275              
276 124           value = (value << 6) + (octet & 0x3F);
277             }
278              
279             /* Check the length of the sequence against the value. */
280              
281 4701 100         if (!((width == 1) ||
    100          
    0          
282 67 50         (width == 2 && value >= 0x80) ||
    50          
283 57 50         (width == 3 && value >= 0x800) ||
284 0 0         (width == 4 && value >= 0x10000)))
285 0           return yaml_parser_set_reader_error(parser,
286             "invalid length of a UTF-8 sequence",
287             parser->offset, -1);
288              
289             /* Check the range of the value. */
290              
291 4701 50         if ((value >= 0xD800 && value <= 0xDFFF) || value > 0x10FFFF)
    0          
    50          
292 0           return yaml_parser_set_reader_error(parser,
293             "invalid Unicode character",
294             parser->offset, value);
295              
296 4701           break;
297              
298             case YAML_UTF16LE_ENCODING:
299             case YAML_UTF16BE_ENCODING:
300              
301 12           low = (parser->encoding == YAML_UTF16LE_ENCODING ? 0 : 1);
302 12           high = (parser->encoding == YAML_UTF16LE_ENCODING ? 1 : 0);
303              
304             /*
305             * The UTF-16 encoding is not as simple as one might
306             * naively think. Check RFC 2781
307             * (http://www.ietf.org/rfc/rfc2781.txt).
308             *
309             * Normally, two subsequent bytes describe a Unicode
310             * character. However a special technique (called a
311             * surrogate pair) is used for specifying character
312             * values larger than 0xFFFF.
313             *
314             * A surrogate pair consists of two pseudo-characters:
315             * high surrogate area (0xD800-0xDBFF)
316             * low surrogate area (0xDC00-0xDFFF)
317             *
318             * The following formulas are used for decoding
319             * and encoding characters using surrogate pairs:
320             *
321             * U = U' + 0x10000 (0x01 00 00 <= U <= 0x10 FF FF)
322             * U' = yyyyyyyyyyxxxxxxxxxx (0 <= U' <= 0x0F FF FF)
323             * W1 = 110110yyyyyyyyyy
324             * W2 = 110111xxxxxxxxxx
325             *
326             * where U is the character value, W1 is the high surrogate
327             * area, W2 is the low surrogate area.
328             */
329              
330             /* Check for incomplete UTF-16 character. */
331              
332 12 50         if (raw_unread < 2) {
333 0 0         if (parser->eof) {
334 0           return yaml_parser_set_reader_error(parser,
335             "incomplete UTF-16 character",
336             parser->offset, -1);
337             }
338 0           incomplete = 1;
339 0           break;
340             }
341              
342             /* Get the character. */
343              
344 24           value = parser->raw_buffer.pointer[low]
345 12           + (parser->raw_buffer.pointer[high] << 8);
346              
347             /* Check for unexpected low surrogate area. */
348              
349 12 50         if ((value & 0xFC00) == 0xDC00)
350 0           return yaml_parser_set_reader_error(parser,
351             "unexpected low surrogate area",
352             parser->offset, value);
353              
354             /* Check for a high surrogate area. */
355              
356 12 50         if ((value & 0xFC00) == 0xD800) {
357              
358 0           width = 4;
359              
360             /* Check for incomplete surrogate pair. */
361              
362 0 0         if (raw_unread < 4) {
363 0 0         if (parser->eof) {
364 0           return yaml_parser_set_reader_error(parser,
365             "incomplete UTF-16 surrogate pair",
366             parser->offset, -1);
367             }
368 0           incomplete = 1;
369 0           break;
370             }
371              
372             /* Get the next character. */
373              
374 0           value2 = parser->raw_buffer.pointer[low+2]
375 0           + (parser->raw_buffer.pointer[high+2] << 8);
376              
377             /* Check for a low surrogate area. */
378              
379 0 0         if ((value2 & 0xFC00) != 0xDC00)
380 0           return yaml_parser_set_reader_error(parser,
381             "expected low surrogate area",
382 0           parser->offset+2, value2);
383              
384             /* Generate the value of the surrogate pair. */
385              
386 0           value = 0x10000 + ((value & 0x3FF) << 10) + (value2 & 0x3FF);
387             }
388              
389             else {
390 12           width = 2;
391             }
392              
393 12           break;
394              
395             default:
396             assert(1); /* Impossible. */
397             }
398              
399             /* Check if the raw buffer contains enough bytes to form a character. */
400              
401 4713 50         if (incomplete) break;
402              
403             /*
404             * Check if the character is in the allowed range:
405             * #x9 | #xA | #xD | [#x20-#x7E] (8 bit)
406             * | #x85 | [#xA0-#xD7FF] | [#xE000-#xFFFD] (16 bit)
407             * | [#x10000-#x10FFFF] (32 bit)
408             */
409              
410 4717 50         if (! (value == 0x09 || value == 0x0A || value == 0x0D
    100          
    50          
    50          
411 4361 100         || (value >= 0x20 && value <= 0x7E)
    100          
412 73 50         || (value == 0x85) || (value >= 0xA0 && value <= 0xD7FF)
    100          
    50          
413 4 50         || (value >= 0xE000 && value <= 0xFFFD)
    0          
414 0 0         || (value >= 0x10000 && value <= 0x10FFFF))) {
415 4           (void)yaml_parser_set_reader_error(parser,
416             "control characters are not allowed",
417             parser->offset, value);
418 4 100         if (!parser->problem_nonstrict)
419 1           return 0;
420             }
421              
422             /* Move the raw pointers. */
423              
424 4712           parser->raw_buffer.pointer += width;
425 4712           parser->offset += width;
426              
427             /* Finally put the character into the buffer. */
428              
429             /* 0000 0000-0000 007F -> 0xxxxxxx */
430 4712 100         if (value <= 0x7F) {
431 4643           *(parser->buffer.last++) = value;
432             }
433             /* 0000 0080-0000 07FF -> 110xxxxx 10xxxxxx */
434 69 100         else if (value <= 0x7FF) {
435 12           *(parser->buffer.last++) = 0xC0 + (value >> 6);
436 12           *(parser->buffer.last++) = 0x80 + (value & 0x3F);
437             }
438             /* 0000 0800-0000 FFFF -> 1110xxxx 10xxxxxx 10xxxxxx */
439 57 50         else if (value <= 0xFFFF) {
440 57           *(parser->buffer.last++) = 0xE0 + (value >> 12);
441 57           *(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F);
442 57           *(parser->buffer.last++) = 0x80 + (value & 0x3F);
443             }
444             /* 0001 0000-0010 FFFF -> 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
445             else {
446 0           *(parser->buffer.last++) = 0xF0 + (value >> 18);
447 0           *(parser->buffer.last++) = 0x80 + ((value >> 12) & 0x3F);
448 0           *(parser->buffer.last++) = 0x80 + ((value >> 6) & 0x3F);
449 0           *(parser->buffer.last++) = 0x80 + (value & 0x3F);
450             }
451              
452 4712           parser->unread ++;
453             }
454              
455             /* On EOF, put NUL into the buffer and return. */
456              
457 210 100         if (parser->eof) {
458 104           *(parser->buffer.last++) = '\0';
459 104           parser->unread ++;
460 104           return 1;
461             }
462              
463             }
464              
465 106 50         if (parser->offset >= MAX_FILE_SIZE) {
466 0           return yaml_parser_set_reader_error(parser, "input is too long",
467             parser->offset, -1);
468             }
469              
470 106           return 1;
471             }