dotdot.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 
23 #include "curl_setup.h"
24 
25 #include <curl/curl.h>
26 
27 #include "dotdot.h"
28 #include "curl_memory.h"
29 
30 /* The last #include file should be: */
31 #include "memdebug.h"
32 
33 /*
34  * "Remove Dot Segments"
35  * https://tools.ietf.org/html/rfc3986#section-5.2.4
36  */
37 
38 /*
39  * Curl_dedotdotify()
40  * @unittest: 1395
41  *
42  * This function gets a zero-terminated path with dot and dotdot sequences
43  * passed in and strips them off according to the rules in RFC 3986 section
44  * 5.2.4.
45  *
46  * The function handles a query part ('?' + stuff) appended but it expects
47  * that fragments ('#' + stuff) have already been cut off.
48  *
49  * RETURNS
50  *
51  * an allocated dedotdotified output string
52  */
53 char *Curl_dedotdotify(const char *input)
54 {
55  size_t inlen = strlen(input);
56  char *clone;
57  size_t clen = inlen; /* the length of the cloned input */
58  char *out = malloc(inlen + 1);
59  char *outptr;
60  char *orgclone;
61  char *queryp;
62  if(!out)
63  return NULL; /* out of memory */
64 
65  /* get a cloned copy of the input */
66  clone = strdup(input);
67  if(!clone) {
68  free(out);
69  return NULL;
70  }
71  orgclone = clone;
72  outptr = out;
73 
74  if(!*clone) {
75  /* zero length string, return that */
76  free(out);
77  return clone;
78  }
79 
80  /*
81  * To handle query-parts properly, we must find it and remove it during the
82  * dotdot-operation and then append it again at the end to the output
83  * string.
84  */
85  queryp = strchr(clone, '?');
86  if(queryp)
87  *queryp = 0;
88 
89  do {
90 
91  /* A. If the input buffer begins with a prefix of "../" or "./", then
92  remove that prefix from the input buffer; otherwise, */
93 
94  if(!strncmp("./", clone, 2)) {
95  clone += 2;
96  clen -= 2;
97  }
98  else if(!strncmp("../", clone, 3)) {
99  clone += 3;
100  clen -= 3;
101  }
102 
103  /* B. if the input buffer begins with a prefix of "/./" or "/.", where
104  "." is a complete path segment, then replace that prefix with "/" in
105  the input buffer; otherwise, */
106  else if(!strncmp("/./", clone, 3)) {
107  clone += 2;
108  clen -= 2;
109  }
110  else if(!strcmp("/.", clone)) {
111  clone[1]='/';
112  clone++;
113  clen -= 1;
114  }
115 
116  /* C. if the input buffer begins with a prefix of "/../" or "/..", where
117  ".." is a complete path segment, then replace that prefix with "/" in
118  the input buffer and remove the last segment and its preceding "/" (if
119  any) from the output buffer; otherwise, */
120 
121  else if(!strncmp("/../", clone, 4)) {
122  clone += 3;
123  clen -= 3;
124  /* remove the last segment from the output buffer */
125  while(outptr > out) {
126  outptr--;
127  if(*outptr == '/')
128  break;
129  }
130  *outptr = 0; /* zero-terminate where it stops */
131  }
132  else if(!strcmp("/..", clone)) {
133  clone[2]='/';
134  clone += 2;
135  clen -= 2;
136  /* remove the last segment from the output buffer */
137  while(outptr > out) {
138  outptr--;
139  if(*outptr == '/')
140  break;
141  }
142  *outptr = 0; /* zero-terminate where it stops */
143  }
144 
145  /* D. if the input buffer consists only of "." or "..", then remove
146  that from the input buffer; otherwise, */
147 
148  else if(!strcmp(".", clone) || !strcmp("..", clone)) {
149  *clone = 0;
150  *out = 0;
151  }
152 
153  else {
154  /* E. move the first path segment in the input buffer to the end of
155  the output buffer, including the initial "/" character (if any) and
156  any subsequent characters up to, but not including, the next "/"
157  character or the end of the input buffer. */
158 
159  do {
160  *outptr++ = *clone++;
161  clen--;
162  } while(*clone && (*clone != '/'));
163  *outptr = 0;
164  }
165 
166  } while(*clone);
167 
168  if(queryp) {
169  size_t qlen;
170  /* There was a query part, append that to the output. The 'clone' string
171  may now have been altered so we copy from the original input string
172  from the correct index. */
173  size_t oindex = queryp - orgclone;
174  qlen = strlen(&input[oindex]);
175  memcpy(outptr, &input[oindex], qlen + 1); /* include the end zero byte */
176  }
177 
178  free(orgclone);
179  return out;
180 }
#define free(ptr)
Definition: curl_memory.h:130
#define strdup(ptr)
Definition: curl_memory.h:122
#define malloc(size)
Definition: curl_memory.h:124
memcpy(filename, filename1, strlen(filename1))
char * Curl_dedotdotify(const char *input)
Definition: dotdot.c:53


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:08