← Commit list

91e0ed51a5

Max Dymond
Max Dymond
2026-09-15
SUCCESS Duration: 385s

Subject

glob: reduce the number of allocations for URLs that don't need globbing.

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

src/tool_operate.c+5 -3
@@ -1242,10 +1242,11 @@ static CURLcode setup_input_file(struct OperationConfig *config,
if(!config->globoff && !glob_inuse(&state->inglob))
result = glob_url(&state->inglob, u->infile, &state->upnum, err);
if(!result && !state->uploadfile) {
- if(glob_inuse(&state->inglob))
+ if(glob_inuse(&state->inglob) &&
+ !glob_is_literal(&state->inglob))
result = glob_next_url(&state->uploadfile, &state->inglob);
else if(!state->upidx) {
- /* copy the allocated string */
+ /* take ownership of the allocated string */
state->uploadfile = u->infile;
u->infile = NULL;
}
@@ -1305,7 +1306,8 @@ static CURLcode select_next_url(struct State *state,
char **url)
{
CURLcode result = CURLE_OK;
- if(glob_inuse(&state->urlglob))
+ if(glob_inuse(&state->urlglob) &&
+ !glob_is_literal(&state->urlglob))
result = glob_next_url(url, &state->urlglob);
else if(!state->urlidx) {
*url = curlx_strdup(u->url);
src/tool_urlglob.c+16 -1
@@ -543,7 +543,13 @@ static CURLcode glob_parse(struct URLGlob *glob, const char *pattern,
bool glob_inuse(struct URLGlob *glob)
{
- return glob->palloc ? TRUE : FALSE;
+ /* Both parsed patterns and a literal URL make the glob active. */
+ return (glob->palloc || glob->literal) ? TRUE : FALSE;
+}
+
+bool glob_is_literal(const struct URLGlob *glob)
+{
+ return glob->literal;
}
/* a glob error has been confirmed, this outputs details about it to the set
@@ -578,6 +584,12 @@ CURLcode glob_url(struct URLGlob *glob, const char *url, curl_off_t *urlnum,
memset(glob, 0, sizeof(struct URLGlob));
curlx_dyn_init(&glob->buf, MAX_CONFIG_LINE_LENGTH);
+ if(!strpbrk(url, "{}[]")) {
+ /* no glob syntax: use the URL as-is instead of parsing a copy of it */
+ glob->literal = TRUE;
+ *urlnum = 1;
+ return CURLE_OK;
+ }
glob->pattern = curlx_malloc(2 * sizeof(struct URLPattern));
if(!glob->pattern)
return CURLE_OUT_OF_MEMORY;
@@ -598,6 +610,8 @@ void glob_cleanup(struct URLGlob *glob)
{
size_t i;
+ glob->literal = FALSE;
+ glob->beenhere = 0;
if(glob->pattern) {
for(i = 0; i < glob->pnum; i++) {
DEBUGASSERT(glob->pattern[i].type);
@@ -622,6 +636,7 @@ CURLcode glob_next_url(char **globbed, struct URLGlob *glob)
size_t i;
*globbed = NULL;
+ DEBUGASSERT(!glob->literal);
curlx_dyn_reset(&glob->buf);
if(!glob->beenhere)
src/tool_urlglob.h+2 -0
@@ -65,6 +65,7 @@ struct URLPattern {
struct URLGlob {
struct dynbuf buf;
struct URLPattern *pattern;
+ bool literal;
size_t palloc; /* number of pattern entries allocated */
size_t pnum; /* number of patterns used */
char beenhere;
@@ -83,5 +84,6 @@ CURLcode glob_match_url(char **output, const char *filename,
SANITIZEcode *sc);
void glob_cleanup(struct URLGlob *glob);
bool glob_inuse(struct URLGlob *glob);
+bool glob_is_literal(const struct URLGlob *glob);
#endif /* HEADER_CURL_TOOL_URLGLOB_H */
tests/data/Makefile.am+1 -0
@@ -1964,6 +1964,7 @@ TESTCASES = \
test2412 \
test2413 \
test2414 \
+ test2415 \
test2429 \
test2453 \
\
tests/data/test2415+36 -0
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+globbing
+</keywords>
+</info>
+# Server-side
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<name>
+reference a named glob with a literal URL
+</name>
+<command option="no-output">
+"%HOSTIP:%HTTPPORT/test" -o "somewhere/#%LTfoo%GT"
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<stderr mode="text">
+curl: (43) no glob exists with this name in position 16:
+somewhere/#%LTfoo%GT
+ ^
+</stderr>
+<errorcode>
+43
+</errorcode>
+</verify>
+</testcase>