Fossil SCM

URL @ parsing fix: Do not connect to evil.example when given https://[email protected]/r . From libfossil.

danshearer 2026-10-11 21:07 UTC trunk
Commit c6fbe0c05a2964dcce2d5030b32d8e0e2b85ba4b1b069ba8a3c7006084a68220
1 file changed +8 -3
+8 -3
--- src/url.c
+++ src/url.c
@@ -174,11 +174,14 @@
174174
pUrlData->isHttps = 0;
175175
pUrlData->protocol = "http";
176176
pUrlData->dfltPort = 80;
177177
iStart = 7;
178178
}
179
- for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!='@'; i++){}
179
+ /* The user-id ends at an '@' that comes before the path, query,
180
+ ** or fragment. An '@' after any of them belongs to that part. */
181
+ for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!='?' && c!='#' && c!='@';
182
+ i++){}
180183
if( c=='@' ){
181184
/* Parse up the user-id and password */
182185
for(j=iStart; j<i && zUrl[j]!=':'; j++){}
183186
pUrlData->user = mprintf("%.*s", j-iStart, &zUrl[iStart]);
184187
dehttpize(pUrlData->user);
@@ -195,17 +198,19 @@
195198
if( urlFlags & URL_OMIT_USER ){
196199
zLogin = mprintf("");
197200
}else{
198201
zLogin = mprintf("%t@", pUrlData->user);
199202
}
200
- for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
203
+ for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!='?' && c!='#' && c!=':';
204
+ j++){}
201205
pUrlData->name = mprintf("%.*s", j-i-1, &zUrl[i+1]);
202206
i = j;
203207
}else{
204208
int inSquare = 0;
205209
int n;
206
- for(i=iStart; (c=zUrl[i])!=0 && c!='/' && (inSquare || c!=':'); i++){
210
+ for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!='?' && c!='#'
211
+ && (inSquare || c!=':'); i++){
207212
if( c=='[' ) inSquare = 1;
208213
if( c==']' ) inSquare = 0;
209214
}
210215
pUrlData->name = mprintf("%.*s", i-iStart, &zUrl[iStart]);
211216
n = strlen(pUrlData->name);
212217
--- src/url.c
+++ src/url.c
@@ -174,11 +174,14 @@
174 pUrlData->isHttps = 0;
175 pUrlData->protocol = "http";
176 pUrlData->dfltPort = 80;
177 iStart = 7;
178 }
179 for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!='@'; i++){}
 
 
 
180 if( c=='@' ){
181 /* Parse up the user-id and password */
182 for(j=iStart; j<i && zUrl[j]!=':'; j++){}
183 pUrlData->user = mprintf("%.*s", j-iStart, &zUrl[iStart]);
184 dehttpize(pUrlData->user);
@@ -195,17 +198,19 @@
195 if( urlFlags & URL_OMIT_USER ){
196 zLogin = mprintf("");
197 }else{
198 zLogin = mprintf("%t@", pUrlData->user);
199 }
200 for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
 
201 pUrlData->name = mprintf("%.*s", j-i-1, &zUrl[i+1]);
202 i = j;
203 }else{
204 int inSquare = 0;
205 int n;
206 for(i=iStart; (c=zUrl[i])!=0 && c!='/' && (inSquare || c!=':'); i++){
 
207 if( c=='[' ) inSquare = 1;
208 if( c==']' ) inSquare = 0;
209 }
210 pUrlData->name = mprintf("%.*s", i-iStart, &zUrl[iStart]);
211 n = strlen(pUrlData->name);
212
--- src/url.c
+++ src/url.c
@@ -174,11 +174,14 @@
174 pUrlData->isHttps = 0;
175 pUrlData->protocol = "http";
176 pUrlData->dfltPort = 80;
177 iStart = 7;
178 }
179 /* The user-id ends at an '@' that comes before the path, query,
180 ** or fragment. An '@' after any of them belongs to that part. */
181 for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!='?' && c!='#' && c!='@';
182 i++){}
183 if( c=='@' ){
184 /* Parse up the user-id and password */
185 for(j=iStart; j<i && zUrl[j]!=':'; j++){}
186 pUrlData->user = mprintf("%.*s", j-iStart, &zUrl[iStart]);
187 dehttpize(pUrlData->user);
@@ -195,17 +198,19 @@
198 if( urlFlags & URL_OMIT_USER ){
199 zLogin = mprintf("");
200 }else{
201 zLogin = mprintf("%t@", pUrlData->user);
202 }
203 for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!='?' && c!='#' && c!=':';
204 j++){}
205 pUrlData->name = mprintf("%.*s", j-i-1, &zUrl[i+1]);
206 i = j;
207 }else{
208 int inSquare = 0;
209 int n;
210 for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!='?' && c!='#'
211 && (inSquare || c!=':'); i++){
212 if( c=='[' ) inSquare = 1;
213 if( c==']' ) inSquare = 0;
214 }
215 pUrlData->name = mprintf("%.*s", i-iStart, &zUrl[iStart]);
216 n = strlen(pUrlData->name);
217

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button