File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / dotdot.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (4 years, 1 month ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    1: /***************************************************************************
    2:  *                                  _   _ ____  _
    3:  *  Project                     ___| | | |  _ \| |
    4:  *                             / __| | | | |_) | |
    5:  *                            | (__| |_| |  _ <| |___
    6:  *                             \___|\___/|_| \_\_____|
    7:  *
    8:  * Copyright (C) 1998 - 2019, 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:   *out = 0; /* zero terminates, for inputs like "./" */
   66: 
   67:   /* get a cloned copy of the input */
   68:   clone = strdup(input);
   69:   if(!clone) {
   70:     free(out);
   71:     return NULL;
   72:   }
   73:   orgclone = clone;
   74:   outptr = out;
   75: 
   76:   if(!*clone) {
   77:     /* zero length string, return that */
   78:     free(out);
   79:     return clone;
   80:   }
   81: 
   82:   /*
   83:    * To handle query-parts properly, we must find it and remove it during the
   84:    * dotdot-operation and then append it again at the end to the output
   85:    * string.
   86:    */
   87:   queryp = strchr(clone, '?');
   88:   if(queryp)
   89:     *queryp = 0;
   90: 
   91:   do {
   92: 
   93:     /*  A.  If the input buffer begins with a prefix of "../" or "./", then
   94:         remove that prefix from the input buffer; otherwise, */
   95: 
   96:     if(!strncmp("./", clone, 2)) {
   97:       clone += 2;
   98:       clen -= 2;
   99:     }
  100:     else if(!strncmp("../", clone, 3)) {
  101:       clone += 3;
  102:       clen -= 3;
  103:     }
  104: 
  105:     /*  B.  if the input buffer begins with a prefix of "/./" or "/.", where
  106:         "."  is a complete path segment, then replace that prefix with "/" in
  107:         the input buffer; otherwise, */
  108:     else if(!strncmp("/./", clone, 3)) {
  109:       clone += 2;
  110:       clen -= 2;
  111:     }
  112:     else if(!strcmp("/.", clone)) {
  113:       clone[1]='/';
  114:       clone++;
  115:       clen -= 1;
  116:     }
  117: 
  118:     /*  C.  if the input buffer begins with a prefix of "/../" or "/..", where
  119:         ".." is a complete path segment, then replace that prefix with "/" in
  120:         the input buffer and remove the last segment and its preceding "/" (if
  121:         any) from the output buffer; otherwise, */
  122: 
  123:     else if(!strncmp("/../", clone, 4)) {
  124:       clone += 3;
  125:       clen -= 3;
  126:       /* remove the last segment from the output buffer */
  127:       while(outptr > out) {
  128:         outptr--;
  129:         if(*outptr == '/')
  130:           break;
  131:       }
  132:       *outptr = 0; /* zero-terminate where it stops */
  133:     }
  134:     else if(!strcmp("/..", clone)) {
  135:       clone[2]='/';
  136:       clone += 2;
  137:       clen -= 2;
  138:       /* remove the last segment from the output buffer */
  139:       while(outptr > out) {
  140:         outptr--;
  141:         if(*outptr == '/')
  142:           break;
  143:       }
  144:       *outptr = 0; /* zero-terminate where it stops */
  145:     }
  146: 
  147:     /*  D.  if the input buffer consists only of "." or "..", then remove
  148:         that from the input buffer; otherwise, */
  149: 
  150:     else if(!strcmp(".", clone) || !strcmp("..", clone)) {
  151:       *clone = 0;
  152:       *out = 0;
  153:     }
  154: 
  155:     else {
  156:       /*  E.  move the first path segment in the input buffer to the end of
  157:           the output buffer, including the initial "/" character (if any) and
  158:           any subsequent characters up to, but not including, the next "/"
  159:           character or the end of the input buffer. */
  160: 
  161:       do {
  162:         *outptr++ = *clone++;
  163:         clen--;
  164:       } while(*clone && (*clone != '/'));
  165:       *outptr = 0;
  166:     }
  167: 
  168:   } while(*clone);
  169: 
  170:   if(queryp) {
  171:     size_t qlen;
  172:     /* There was a query part, append that to the output. The 'clone' string
  173:        may now have been altered so we copy from the original input string
  174:        from the correct index. */
  175:     size_t oindex = queryp - orgclone;
  176:     qlen = strlen(&input[oindex]);
  177:     memcpy(outptr, &input[oindex], qlen + 1); /* include the end zero byte */
  178:   }
  179: 
  180:   free(orgclone);
  181:   return out;
  182: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>