mirror of
https://github.com/curl/curl.git
synced 2026-08-25 00:33:31 +03:00
strparse: string parsing helper functions
Designed to aid converting off from sscanf parsers. sscanf is hard to use right, easy to mess up and often makes for sloppy error checking. The new parsers allow more exact and pedandic parsing. This new set of functions should be possible to use (and extend) and switch over other libcurl parser code to use going forward. Adapts the following to use the new functions: - altsvc.c - hsts.c - http_aws_sigv4.c Bonus: fewer memory copies, fewer stack buffers. Test: Unit test1664 Docs: docs/internals/STRPARSE.md Closes #15692
This commit is contained in:
parent
ff5091aa9f
commit
d5c738c608
20 changed files with 912 additions and 163 deletions
|
|
@ -453,6 +453,7 @@ Features testable here are:
|
|||
- `Kerberos`
|
||||
- `Largefile`
|
||||
- `large-time` (time_t is larger than 32-bit)
|
||||
- `large-size` (size_t is larger than 32-bit)
|
||||
- `ld_preload`
|
||||
- `libssh2`
|
||||
- `libssh`
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ test1620 test1621 \
|
|||
test1630 test1631 test1632 test1633 test1634 test1635 \
|
||||
\
|
||||
test1650 test1651 test1652 test1653 test1654 test1655 test1656 \
|
||||
test1660 test1661 test1662 test1663 \
|
||||
test1660 test1661 test1662 test1663 test1664 \
|
||||
\
|
||||
test1670 test1671 \
|
||||
\
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@ alt-svc
|
|||
%LOGDIR/%TESTNUMBER
|
||||
</command>
|
||||
<file name="%LOGDIR/%TESTNUMBER" mode="text">
|
||||
h2 example.com 443 h3 shiny.example.com 8443 "20191231 00:00:00" 0 1
|
||||
h2 example.com 443 h3 shiny.example.com 8443 "20191231 00:00:00" 0 0
|
||||
# a comment
|
||||
h2 foo.example.com 443 h3 shiny.example.com 8443 "20291231 23:30:00" 0 1
|
||||
h1 example.com 443 h3 shiny.example.com 8443 "20121231 00:00:01" 0 1
|
||||
h3 example.com 443 h3 shiny.example.com 8443 "20131231 00:00:00" 0 1
|
||||
h2 foo.example.com 443 h3 shiny.example.com 8443 "20291231 23:30:00" 0 0
|
||||
h1 example.com 443 h3 shiny.example.com 8443 "20121231 00:00:01" 0 0
|
||||
h3 example.com 443 h3 shiny.example.com 8443 "20131231 00:00:00" 0 0
|
||||
# also a comment
|
||||
bad example.com 443 h3 shiny.example.com 8443 "20191231 00:00:00" 0 1
|
||||
bad example.com 443 h3 shiny.example.com 8443 "20191231 00:00:00" 0 0
|
||||
rubbish
|
||||
</file>
|
||||
</client>
|
||||
|
|
@ -41,10 +41,10 @@ rubbish
|
|||
<file name="%LOGDIR/%TESTNUMBER-out" mode="text">
|
||||
# Your alt-svc cache. https://curl.se/docs/alt-svc.html
|
||||
# This file was generated by libcurl! Edit at your own risk.
|
||||
h2 example.com 443 h3 shiny.example.com 8443 "20191231 00:00:00" 0 1
|
||||
h2 foo.example.com 443 h3 shiny.example.com 8443 "20291231 23:30:00" 0 1
|
||||
h1 example.com 443 h3 shiny.example.com 8443 "20121231 00:00:01" 0 1
|
||||
h3 example.com 443 h3 shiny.example.com 8443 "20131231 00:00:00" 0 1
|
||||
h2 example.com 443 h3 shiny.example.com 8443 "20191231 00:00:00" 0 0
|
||||
h2 foo.example.com 443 h3 shiny.example.com 8443 "20291231 23:30:00" 0 0
|
||||
h1 example.com 443 h3 shiny.example.com 8443 "20121231 00:00:01" 0 0
|
||||
h3 example.com 443 h3 shiny.example.com 8443 "20131231 00:00:00" 0 0
|
||||
h1 example.org 8080 h2 example.com 8080 "20190125 22:34:21" 0 0
|
||||
h1 2.example.org 8080 h3 2.example.org 8080 "20190125 22:34:21" 0 0
|
||||
h1 3.example.org 8080 h2 example.com 8080 "20190125 22:34:21" 0 0
|
||||
|
|
|
|||
120
tests/data/test1664
Normal file
120
tests/data/test1664
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
unittest
|
||||
strparse
|
||||
</keywords>
|
||||
</info>
|
||||
|
||||
#
|
||||
# Client-side
|
||||
<client>
|
||||
<server>
|
||||
none
|
||||
</server>
|
||||
<features>
|
||||
unittest
|
||||
large-size
|
||||
</features>
|
||||
<name>
|
||||
unit tests for strparse.c string parsing functions
|
||||
</name>
|
||||
</client>
|
||||
|
||||
<verify>
|
||||
<stdout>
|
||||
Curl_str_word
|
||||
0: ("word") 0, "word" [4], line 4
|
||||
1: ("word ") 0, "word" [4], line 4
|
||||
2: (" word ") 2, "" [0], line 0
|
||||
3: ("wo rd") 0, "wo" [2], line 2
|
||||
4: ("word(") 0, "word(" [5], line 5
|
||||
5: ("wor(d") 0, "wor(d" [5], line 5
|
||||
6: ("perfect") 0, "perfect" [7], line 7
|
||||
7: ("") 2, "" [0], line 0
|
||||
8: ("longerth") 1, "" [0], line 0
|
||||
Curl_str_until
|
||||
0: ("word") 0, "wor" [3], line 3
|
||||
1: ("word ") 0, "wor" [3], line 3
|
||||
2: (" word ") 0, " wor" [4], line 4
|
||||
3: ("wo rd") 0, "wo r" [4], line 4
|
||||
4: ("word(") 0, "wor" [3], line 3
|
||||
5: ("wor(d") 0, "wor(" [4], line 4
|
||||
6: ("perfect") 0, "perfect" [7], line 7
|
||||
7: ("") 2, "" [0], line 0
|
||||
8: ("longerth") 1, "" [0], line 0
|
||||
Curl_str_quotedword
|
||||
0: (""word"") 0, "word" [4], line 6
|
||||
1: (""word") 4, "" [0], line 0
|
||||
2: ("word"") 3, "" [0], line 0
|
||||
3: (""word""") 0, "word" [4], line 6
|
||||
4: (""word" ") 0, "word" [4], line 6
|
||||
5: (" "word"") 3, "" [0], line 0
|
||||
6: (""perfect"") 0, "perfect" [7], line 9
|
||||
7: (""p r e t"") 0, "p r e t" [7], line 9
|
||||
8: (""perfec\"") 0, "perfec\" [7], line 9
|
||||
9: ("""") 0, "" [0], line 2
|
||||
10: ("") 3, "" [0], line 0
|
||||
11: (""longerth"") 1, "" [0], line 0
|
||||
Curl_str_single
|
||||
0: ("a") 0, line 1
|
||||
1: ("aa") 0, line 1
|
||||
2: ("A") 5, line 0
|
||||
3: ("b") 5, line 0
|
||||
4: ("\") 5, line 0
|
||||
5: (" ") 5, line 0
|
||||
6: ("") 5, line 0
|
||||
Curl_str_singlespace
|
||||
0: ("a") 5, line 0
|
||||
1: ("aa") 5, line 0
|
||||
2: ("A") 5, line 0
|
||||
3: ("b") 5, line 0
|
||||
4: ("\") 5, line 0
|
||||
5: (" ") 0, line 1
|
||||
6: (" ") 5, line 0
|
||||
7: ("
|
||||
") 5, line 0
|
||||
8: ("") 5, line 0
|
||||
Curl_str_single
|
||||
0: ("a") 0, line 1
|
||||
1: ("aa") 0, line 1
|
||||
2: ("A") 5, line 0
|
||||
3: ("b") 5, line 0
|
||||
4: ("\") 5, line 0
|
||||
5: (" ") 5, line 0
|
||||
6: ("") 5, line 0
|
||||
Curl_str_number
|
||||
0: ("1") 0, [1] line 1
|
||||
1: ("10000") 1, [0] line 4
|
||||
2: ("1234") 0, [1234] line 4
|
||||
3: ("1235") 0, [1235] line 4
|
||||
4: ("1236") 1, [0] line 3
|
||||
5: ("01234") 0, [1234] line 5
|
||||
6: ("00000000000000000000000000001234") 0, [1234] line 32
|
||||
7: ("0123 345") 0, [123] line 4
|
||||
8: ("0123O345") 0, [123] line 4
|
||||
9: ("-12") 0, [0] line 0
|
||||
10: (" 123") 0, [0] line 0
|
||||
11: ("") 0, [0] line 0
|
||||
Curl_str_number / max
|
||||
0: ("9223372036854775808") 0, [9223372036854775808] line 19
|
||||
1: ("9223372036854775809") 0, [9223372036854775809] line 19
|
||||
2: ("18446744073709551615") 0, [18446744073709551615] line 20
|
||||
3: ("18446744073709551616") 7, [0] line 19
|
||||
4: ("18446744073709551617") 7, [0] line 19
|
||||
Curl_str_newline
|
||||
0: ("a") 6, line 0
|
||||
1: ("aa") 6, line 0
|
||||
2: ("A") 6, line 0
|
||||
3: ("b") 6, line 0
|
||||
4: ("\") 6, line 0
|
||||
5: (" ") 6, line 0
|
||||
6: ("
|
||||
") 0, line 1
|
||||
7: ("
") 0, line 1
|
||||
8: ("
|
||||
") 0, line 1
|
||||
9: ("") 6, line 0
|
||||
</stdout>
|
||||
</verify>
|
||||
</testcase>
|
||||
|
|
@ -823,6 +823,7 @@ sub checksystemfeatures {
|
|||
$feature{"headers-api"} = 1;
|
||||
$feature{"xattr"} = 1;
|
||||
$feature{"large-time"} = 1;
|
||||
$feature{"large-size"} = 1;
|
||||
$feature{"sha512-256"} = 1;
|
||||
$feature{"local-http"} = servers::localhttp();
|
||||
$feature{"codeset-utf8"} = lc(langinfo(CODESET())) eq "utf-8";
|
||||
|
|
|
|||
|
|
@ -101,6 +101,9 @@ static const char *disabled[]={
|
|||
#if (SIZEOF_TIME_T < 5)
|
||||
"large-time",
|
||||
#endif
|
||||
#if (SIZEOF_SIZE_T < 5)
|
||||
"large-size",
|
||||
#endif
|
||||
#ifndef CURL_HAVE_SHA512_256
|
||||
"sha512-256",
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ UNITPROGS = unit1300 unit1302 unit1303 unit1304 unit1305 unit1307 \
|
|||
unit1608 unit1609 unit1610 unit1611 unit1612 unit1614 unit1615 unit1616 \
|
||||
unit1620 unit1621 \
|
||||
unit1650 unit1651 unit1652 unit1653 unit1654 unit1655 unit1656 \
|
||||
unit1660 unit1661 unit1663 \
|
||||
unit1660 unit1661 unit1663 unit1664 \
|
||||
unit2600 unit2601 unit2602 unit2603 unit2604 \
|
||||
unit3200 \
|
||||
unit3205
|
||||
|
|
@ -132,6 +132,8 @@ unit1661_SOURCES = unit1661.c $(UNITFILES)
|
|||
|
||||
unit1663_SOURCES = unit1663.c $(UNITFILES)
|
||||
|
||||
unit1664_SOURCES = unit1664.c $(UNITFILES)
|
||||
|
||||
unit2600_SOURCES = unit2600.c $(UNITFILES)
|
||||
|
||||
unit2601_SOURCES = unit2601.c $(UNITFILES)
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ UNITTEST_START
|
|||
}
|
||||
|
||||
chost = headers[i].chost ? headers[i].chost : headers[i].host;
|
||||
e = Curl_hsts(h, chost, TRUE);
|
||||
e = Curl_hsts(h, chost, strlen(chost), TRUE);
|
||||
showsts(e, chost);
|
||||
}
|
||||
|
||||
|
|
@ -165,7 +165,7 @@ UNITTEST_START
|
|||
/* verify that it is exists for 7 seconds */
|
||||
chost = "expire.example";
|
||||
for(i = 100; i < 110; i++) {
|
||||
e = Curl_hsts(h, chost, TRUE);
|
||||
e = Curl_hsts(h, chost, strlen(chost), TRUE);
|
||||
showsts(e, chost);
|
||||
deltatime++; /* another second passed */
|
||||
}
|
||||
|
|
|
|||
254
tests/unit/unit1664.c
Normal file
254
tests/unit/unit1664.c
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
#include "curlcheck.h"
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN6_H
|
||||
#include <netinet/in6.h>
|
||||
#endif
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "strparse.h"
|
||||
|
||||
#include "memdebug.h" /* LAST include file */
|
||||
|
||||
static CURLcode unit_setup(void)
|
||||
{
|
||||
CURLcode res = CURLE_OK;
|
||||
global_init(CURL_GLOBAL_ALL);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void unit_stop(void)
|
||||
{
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
UNITTEST_START
|
||||
{
|
||||
static const char *wordparse[] = {
|
||||
"word",
|
||||
"word ",
|
||||
" word ",
|
||||
"wo rd",
|
||||
"word(",
|
||||
"wor(d",
|
||||
"perfect",
|
||||
"",
|
||||
"longerth",
|
||||
NULL
|
||||
};
|
||||
|
||||
int i;
|
||||
printf("Curl_str_word\n");
|
||||
for(i = 0; wordparse[i]; i++) {
|
||||
struct Curl_str out;
|
||||
char *line = (char *)wordparse[i];
|
||||
char *orgline = line;
|
||||
int rc = Curl_str_word(&line, &out, 7);
|
||||
printf("%u: (\"%s\") %d, \"%.*s\" [%d], line %d\n",
|
||||
i, orgline, rc, (int)out.len, out.str, (int)out.len,
|
||||
(int)(line - orgline));
|
||||
}
|
||||
|
||||
printf("Curl_str_until\n");
|
||||
for(i = 0; wordparse[i]; i++) {
|
||||
struct Curl_str out;
|
||||
char *line = (char *)wordparse[i];
|
||||
char *orgline = line;
|
||||
int rc = Curl_str_until(&line, &out, 7, 'd');
|
||||
printf("%u: (\"%s\") %d, \"%.*s\" [%d], line %d\n",
|
||||
i, orgline, rc, (int)out.len, out.str, (int)out.len,
|
||||
(int)(line - orgline));
|
||||
}
|
||||
|
||||
{
|
||||
static const char *qwords[] = {
|
||||
"\"word\"",
|
||||
"\"word",
|
||||
"word\"",
|
||||
"\"word\"\"",
|
||||
"\"word\" ",
|
||||
" \"word\"",
|
||||
"\"perfect\"",
|
||||
"\"p r e t\"",
|
||||
"\"perfec\\\"",
|
||||
"\"\"",
|
||||
"",
|
||||
"\"longerth\"",
|
||||
NULL
|
||||
};
|
||||
|
||||
printf("Curl_str_quotedword\n");
|
||||
for(i = 0; qwords[i]; i++) {
|
||||
struct Curl_str out;
|
||||
char *line = (char *)qwords[i];
|
||||
char *orgline = line;
|
||||
int rc = Curl_str_quotedword(&line, &out, 7);
|
||||
printf("%u: (\"%s\") %d, \"%.*s\" [%d], line %d\n",
|
||||
i, orgline, rc, (int)out.len, out.str, (int)out.len,
|
||||
(int)(line - orgline));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
static const char *single[] = {
|
||||
"a",
|
||||
"aa",
|
||||
"A",
|
||||
"b",
|
||||
"\\",
|
||||
" ",
|
||||
"",
|
||||
NULL
|
||||
};
|
||||
printf("Curl_str_single\n");
|
||||
for(i = 0; single[i]; i++) {
|
||||
char *line = (char *)single[i];
|
||||
char *orgline = line;
|
||||
int rc = Curl_str_single(&line, 'a');
|
||||
printf("%u: (\"%s\") %d, line %d\n",
|
||||
i, orgline, rc, (int)(line - orgline));
|
||||
}
|
||||
}
|
||||
{
|
||||
static const char *single[] = {
|
||||
"a",
|
||||
"aa",
|
||||
"A",
|
||||
"b",
|
||||
"\\",
|
||||
" ",
|
||||
"\t",
|
||||
"\n",
|
||||
"",
|
||||
NULL
|
||||
};
|
||||
printf("Curl_str_singlespace\n");
|
||||
for(i = 0; single[i]; i++) {
|
||||
char *line = (char *)single[i];
|
||||
char *orgline = line;
|
||||
int rc = Curl_str_singlespace(&line);
|
||||
printf("%u: (\"%s\") %d, line %d\n",
|
||||
i, orgline, rc, (int)(line - orgline));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
static const char *single[] = {
|
||||
"a",
|
||||
"aa",
|
||||
"A",
|
||||
"b",
|
||||
"\\",
|
||||
" ",
|
||||
"",
|
||||
NULL
|
||||
};
|
||||
printf("Curl_str_single\n");
|
||||
for(i = 0; single[i]; i++) {
|
||||
char *line = (char *)single[i];
|
||||
char *orgline = line;
|
||||
int rc = Curl_str_single(&line, 'a');
|
||||
printf("%u: (\"%s\") %d, line %d\n",
|
||||
i, orgline, rc, (int)(line - orgline));
|
||||
}
|
||||
}
|
||||
{
|
||||
static const char *nums[] = {
|
||||
"1",
|
||||
"10000",
|
||||
"1234",
|
||||
"1235",
|
||||
"1236",
|
||||
"01234",
|
||||
"00000000000000000000000000001234",
|
||||
"0123 345",
|
||||
"0123O345",
|
||||
"-12",
|
||||
" 123",
|
||||
"",
|
||||
NULL
|
||||
};
|
||||
printf("Curl_str_number\n");
|
||||
for(i = 0; nums[i]; i++) {
|
||||
size_t num;
|
||||
char *line = (char *)nums[i];
|
||||
char *orgline = line;
|
||||
int rc = Curl_str_number(&line, &num, 1235);
|
||||
printf("%u: (\"%s\") %d, [%u] line %d\n",
|
||||
i, orgline, rc, (int)num, (int)(line - orgline));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* SIZE_T_MAX is typically 18446744073709551615 */
|
||||
static const char *nums[] = {
|
||||
"9223372036854775808", /* 2^63 */
|
||||
"9223372036854775809", /* 2^63 + 1 */
|
||||
"18446744073709551615", /* 2^64 - 1 */
|
||||
"18446744073709551616", /* 2^64 */
|
||||
"18446744073709551617", /* 2^64 + 1 */
|
||||
NULL
|
||||
};
|
||||
printf("Curl_str_number / max\n");
|
||||
for(i = 0; nums[i]; i++) {
|
||||
size_t num;
|
||||
char *line = (char *)nums[i];
|
||||
char *orgline = line;
|
||||
int rc = Curl_str_number(&line, &num, SIZE_T_MAX);
|
||||
printf("%u: (\"%s\") %d, [%zu] line %d\n",
|
||||
i, orgline, rc, num, (int)(line - orgline));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
static const char *newl[] = {
|
||||
"a",
|
||||
"aa",
|
||||
"A",
|
||||
"b",
|
||||
"\\",
|
||||
" ",
|
||||
"\n",
|
||||
"\r",
|
||||
"\r\n",
|
||||
"",
|
||||
NULL
|
||||
};
|
||||
printf("Curl_str_newline\n");
|
||||
for(i = 0; newl[i]; i++) {
|
||||
char *line = (char *)newl[i];
|
||||
char *orgline = line;
|
||||
int rc = Curl_str_newline(&line);
|
||||
printf("%u: (\"%s\") %d, line %d\n",
|
||||
i, orgline, rc, (int)(line - orgline));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
UNITTEST_STOP
|
||||
Loading…
Add table
Add a link
Reference in a new issue