LTP GCOV extension - code coverage report
Current view: directory - src - vstr_parse.c
Test: Vstr coverage
Date: 2005-01-10 Instrumented lines: 374
Code covered: 100.0 % Executed lines: 374

       1                 : #define VSTR_PARSE_C
       2                 : /*
       3                 :  *  Copyright (C) 2002, 2003, 2004  James Antill
       4                 :  *
       5                 :  *  This library is free software; you can redistribute it and/or
       6                 :  *  modify it under the terms of the GNU Lesser General Public
       7                 :  *  License as published by the Free Software Foundation; either
       8                 :  *  version 2 of the License, or (at your option) any later version.
       9                 :  *
      10                 :  *  This library is distributed in the hope that it will be useful,
      11                 :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      12                 :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13                 :  *  Lesser General Public License for more details.
      14                 :  *
      15                 :  *  You should have received a copy of the GNU Lesser General Public
      16                 :  *  License along with this library; if not, write to the Free Software
      17                 :  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      18                 :  *
      19                 :  *  email: james@and.org
      20                 :  */
      21                 : /* functions for parsing data out of the Vstr */
      22                 : #include "main.h"
      23                 : 
      24                 : #ifdef HAVE_ASCII_ALPHA
      25                 : # define VSTR__PARSE_NUM_USE_LOCAL 0
      26                 : #else
      27                 : # define VSTR__PARSE_NUM_USE_LOCAL 1
      28                 : #endif
      29                 : 
      30                 : 
      31                 : /* basically uses: [ ]*[-+](0x|0X|0)[0-9a-z_]+ */
      32                 : static int vstr__parse_num_beg(const Vstr_base *base,
      33                 :                                size_t *passed_pos, size_t *passed_len,
      34                 :                                unsigned int flags, int *is_neg, int *is_zeroed,
      35                 :                                unsigned int *err)
      36           45813 : {
      37           45813 :   size_t pos = *passed_pos;
      38           45813 :   size_t len = *passed_len;
      39           45813 :   unsigned int num_base = flags & VSTR__MASK_PARSE_NUM_BASE;
      40           45813 :   int auto_base = FALSE;
      41           45813 :   char num_0 = '0';
      42           45813 :   char let_x_low = 'x';
      43           45813 :   char let_X_high = 'X';
      44           45813 :   char let_b_low = 'b';
      45           45813 :   char let_B_high = 'B';
      46           45813 :   char sym_minus = '-';
      47           45813 :   char sym_plus = '+';
      48           45813 :   char sym_space = ' ';
      49           45813 :   size_t tmp = 0;
      50                 : 
      51           45813 :   if (!num_base)
      52             639 :     auto_base = TRUE;
      53           45174 :   else if (num_base > 36)
      54               5 :     num_base = 36;
      55           45169 :   else if (num_base == 1)
      56               5 :     ++num_base;
      57                 : 
      58           45813 :   assert(!(auto_base && (flags & VSTR_FLAG_PARSE_NUM_NO_BEG_ZERO)));
      59                 : 
      60           45813 :   if (!(flags & VSTR_FLAG_PARSE_NUM_LOCAL))
      61                 :   {
      62           45588 :     num_0 = 0x30;
      63           45588 :     let_x_low = 0x78;
      64           45588 :     let_X_high = 0x58;
      65           45588 :     let_b_low = 0x62;
      66           45588 :     let_B_high = 0x42;
      67           45588 :     sym_minus = 0x2D;
      68           45588 :     sym_plus = 0x2B;
      69           45588 :     sym_space = 0x20;
      70                 :   }
      71                 : 
      72           45813 :   if (flags & VSTR_FLAG_PARSE_NUM_SPACE)
      73                 :   {
      74             519 :     tmp = vstr_spn_chrs_fwd(base, pos, len, &sym_space, 1);
      75             519 :     if (tmp >= len)
      76                 :     {
      77               5 :       *err = VSTR_TYPE_PARSE_NUM_ERR_ONLY_S;
      78               5 :       return (0);
      79                 :     }
      80                 : 
      81             514 :     pos += tmp;
      82             514 :     len -= tmp;
      83                 :   }
      84                 : 
      85           45808 :   if (!(flags & VSTR_FLAG_PARSE_NUM_NO_BEG_PM))
      86                 :   {
      87            7527 :     tmp = vstr_spn_chrs_fwd(base, pos, len, &sym_minus, 1);
      88            7527 :     if (tmp > 1)
      89                 :     {
      90               5 :       *err = VSTR_TYPE_PARSE_NUM_ERR_OOB;
      91               5 :       return (0);
      92                 :     }
      93            7522 :     else if (!tmp)
      94                 :     {
      95            7442 :       tmp = vstr_spn_chrs_fwd(base, pos, len, &sym_plus, 1);
      96            7442 :       if (tmp > 1)
      97                 :       {
      98               5 :         *err = VSTR_TYPE_PARSE_NUM_ERR_OOB;
      99               5 :         return (0);
     100                 :       }
     101                 :     }
     102                 :     else
     103              80 :       *is_neg = TRUE;
     104                 : 
     105            7517 :     pos += tmp;
     106            7517 :     len -= tmp;
     107                 :   }
     108                 : 
     109           45798 :   if (!len)
     110                 :   {
     111              74 :     *err = VSTR_TYPE_PARSE_NUM_ERR_ONLY_SPM;
     112              74 :     return (0);
     113                 :   }
     114                 : 
     115           45724 :   tmp = vstr_spn_chrs_fwd(base, pos, len, &num_0, 1);
     116           45724 :   *is_zeroed = !!tmp;
     117           45724 :   if ((tmp == 1) && (auto_base || (num_base == 16) || (num_base ==  2)))
     118                 :   {
     119             714 :     char xX[2];
     120                 : 
     121             714 :     if (tmp == len)
     122                 :     {
     123             335 :       *passed_len = 0;
     124             335 :       return (1);
     125                 :     }
     126                 : 
     127             379 :     pos += tmp;
     128             379 :     len -= tmp;
     129                 : 
     130             379 :     xX[0] = let_x_low;
     131             379 :     xX[1] = let_X_high;
     132             379 :     tmp = vstr_spn_chrs_fwd(base, pos, len, xX, 2);
     133                 : 
     134             379 :     if (tmp > 1)
     135                 :     { /* It's a 0 */
     136               5 :       *err = VSTR_TYPE_PARSE_NUM_ERR_OOB;
     137               5 :       *passed_len = len;
     138               5 :       return (1);
     139                 :     }
     140             374 :     if (tmp == 1)
     141                 :     {
     142             195 :       if (auto_base)
     143             185 :         num_base = 16;
     144                 : 
     145             195 :       pos += tmp;
     146             195 :       len -= tmp;
     147                 : 
     148             195 :       if (!len)
     149                 :       {
     150               5 :         *passed_pos = pos + len;
     151               5 :         *passed_len = 0;
     152               5 :         *err = VSTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX;
     153               5 :         return (0);
     154                 :       }
     155                 : 
     156             190 :       tmp = vstr_spn_chrs_fwd(base, pos, len, &num_0, 1);
     157                 :     }
     158                 :     else
     159                 :     {
     160             179 :       xX[0] = let_b_low;
     161             179 :       xX[1] = let_B_high;
     162             179 :       tmp = vstr_spn_chrs_fwd(base, pos, len, xX, 2);
     163                 : 
     164             179 :       if (tmp > 1)
     165                 :       { /* It's a 0 */
     166               5 :         *err = VSTR_TYPE_PARSE_NUM_ERR_OOB;
     167               5 :         *passed_len = len;
     168               5 :         return (1);
     169                 :       }
     170             174 :       if (tmp == 1)
     171                 :       {
     172              45 :         if (auto_base)
     173              40 :           num_base =  2;
     174                 : 
     175              45 :         pos += tmp;
     176              45 :         len -= tmp;
     177                 : 
     178              45 :         if (!len)
     179                 :         {
     180               5 :           *passed_pos = pos + len;
     181               5 :           *passed_len = 0;
     182               5 :           *err = VSTR_TYPE_PARSE_NUM_ERR_ONLY_SPMX;
     183               5 :           return (0);
     184                 :         }
     185                 : 
     186              40 :         tmp = vstr_spn_chrs_fwd(base, pos, len, &num_0, 1);
     187                 :       }
     188             129 :       else if (auto_base)
     189              35 :         num_base =  8;
     190                 :     }
     191                 :   }
     192           45010 :   else if (tmp && auto_base)
     193                 :   {
     194              20 :     num_base =  8;
     195              20 :     --tmp;
     196                 :   }
     197           44990 :   else if (auto_base)
     198             334 :     num_base = 10;
     199                 : 
     200           45369 :   if (tmp && (flags & VSTR_FLAG_PARSE_NUM_NO_BEG_ZERO))
     201                 :   {
     202             441 :     *passed_len = len - 1;
     203             441 :     if ((tmp != 1) || (len != 1))
     204             411 :       *err = VSTR_TYPE_PARSE_NUM_ERR_BEG_ZERO;
     205                 : 
     206             441 :     return (1);
     207                 :   }
     208                 : 
     209           44928 :   if (tmp == len)
     210                 :   { /* It's a 0 */
     211            1778 :     *passed_len = 0;
     212            1778 :     return (1);
     213                 :   }
     214                 : 
     215           43150 :   pos += tmp;
     216           43150 :   len -= tmp;
     217                 : 
     218           43150 :   *passed_pos = pos;
     219           43150 :   *passed_len = len;
     220                 : 
     221           43150 :   return (num_base);
     222                 : }
     223                 : 
     224                 : #define VSTR__PARSE_NUM_BEG_A(num_type)                                 \
     225                 :     unsigned int dummy_err;                                             \
     226                 :     num_type ret = 0;                                                   \
     227                 :     unsigned int num_base = 0;                                          \
     228                 :     int is_neg = FALSE;                                                 \
     229                 :     int is_zeroed = FALSE;                                              \
     230                 :     size_t orig_len = len;                                              \
     231                 :     char sym_sep = '_';                                                 \
     232                 :     char ascii_num_end = 0x39;                                          \
     233                 :     char ascii_let_low_end = 0x7A;                                      \
     234                 :     char ascii_let_high_end = 0x5A;                                     \
     235                 :     char local_num_end = '9';                                           \
     236                 :     static const char local_let_low[]  = "abcdefghijklmnopqrstuvwxyz";  \
     237                 :     static const char local_let_high[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";  \
     238                 :                                                                         \
     239                 :     if (ret_len) *ret_len = 0;                                          \
     240                 :     if (!err) err = &dummy_err;                                         \
     241                 :     *err = VSTR_TYPE_PARSE_NUM_ERR_NONE;                                \
     242                 :                                                                         \
     243                 :     if (!(num_base = vstr__parse_num_beg(base, &pos, &len, flags,       \
     244                 :                                          &is_neg, &is_zeroed, err)))    \
     245                 :       return (0);                                                       \
     246                 :     else if (num_base == 1) goto ret_num_len
     247                 : 
     248                 : #define VSTR__PARSE_NUM_BEG_S(num_type)                         \
     249                 :     VSTR__PARSE_NUM_BEG_A(num_type);                            \
     250                 :                                                                 \
     251                 :     if (is_neg && (flags & VSTR_FLAG_PARSE_NUM_NO_NEGATIVE))    \
     252                 :     {                                                           \
     253                 :       *err = VSTR_TYPE_PARSE_NUM_ERR_NEGATIVE;                  \
     254                 :       return (0);                                               \
     255                 :     }
     256                 :        
     257                 : #define VSTR__PARSE_NUM_BEG_U(num_type)         \
     258                 :     VSTR__PARSE_NUM_BEG_A(num_type);            \
     259                 :                                                 \
     260                 :     if (is_neg)                                 \
     261                 :     {                                           \
     262                 :       *err = VSTR_TYPE_PARSE_NUM_ERR_NEGATIVE;  \
     263                 :       return (0);                               \
     264                 :     }
     265                 : 
     266                 : #define VSTR__PARSE_NUM_ASCII() do {                    \
     267                 :       if (!(flags & VSTR_FLAG_PARSE_NUM_LOCAL))         \
     268                 :       {                                                 \
     269                 :         sym_sep = 0x5F;                                 \
     270                 :                                                         \
     271                 :         if (num_base <= 10)                             \
     272                 :           ascii_num_end = 0x30 + num_base - 1;          \
     273                 :         else if (num_base > 10)                         \
     274                 :         {                                               \
     275                 :           ascii_let_low_end  = 0x61 + (num_base - 11);  \
     276                 :           ascii_let_high_end = 0x41 + (num_base - 11);  \
     277                 :         }                                               \
     278                 :       }                                                 \
     279                 :       else if (num_base <= 10)                          \
     280                 :         local_num_end = '0' + num_base - 1;             \
     281                 : } while (FALSE)
     282                 : 
     283                 : #define VSTR__PARSE_NUM_BIN_CALC_NUM(num_type) do {                     \
     284                 :       num_type old_ret = ret;                                           \
     285                 :                                                                         \
     286                 :       ret = (ret * num_base) + add_num;                                 \
     287                 :       if ((flags & VSTR_FLAG_PARSE_NUM_OVERFLOW) &&                     \
     288                 :           (((ret - add_num) / num_base) != old_ret))                    \
     289                 :       {                                                                 \
     290                 :         *err = VSTR_TYPE_PARSE_NUM_ERR_OVERFLOW;                        \
     291                 :         break;                                                          \
     292                 :       }                                                                 \
     293                 :     } while (FALSE)                                                     \
     294                 : 
     295                 : #define VSTR__PARSE_NUM_LOOP_BEG() do {                                 \
     296                 :       int done_once = is_zeroed;                                        \
     297                 :       Vstr_iter iter[1];                                                \
     298                 :       int iter_ret = vstr_iter_fwd_beg(base, pos, len, iter);           \
     299                 :                                                                         \
     300                 :       ASSERT(iter_ret);                                                 \
     301                 :       while (len)                                                       \
     302                 :       {                                                                 \
     303                 :         char scan = vstr_iter_fwd_chr(iter, NULL);                      \
     304                 :         const char *end = NULL;                                         \
     305                 :         unsigned int add_num = 0;                                       \
     306                 :                                                                         \
     307                 :         if (done_once && (scan == sym_sep))                             \
     308                 :         {                                                               \
     309                 :           if (!(flags & VSTR_FLAG_PARSE_NUM_SEP)) break;                \
     310                 :           --len;                                                        \
     311                 :           continue;                                                     \
     312                 :         }                                                               \
     313                 :         else if (VSTR__PARSE_NUM_USE_LOCAL &&                           \
     314                 :                  (flags & VSTR_FLAG_PARSE_NUM_LOCAL))                   \
     315                 :         {                                                               \
     316                 :           if ((scan >= '0') && (scan <= local_num_end))                 \
     317                 :             add_num = (scan - '0');                                     \
     318                 :           else if (num_base <= 10)                                      \
     319                 :             break;                                                      \
     320                 :           else if ((end = vstr_wrap_memchr(local_let_low,  scan,        \
     321                 :                                            num_base - 10)))             \
     322                 :             add_num = 10 + (end - local_let_low);                       \
     323                 :           else if ((end = vstr_wrap_memchr(local_let_high, scan,        \
     324                 :                                            num_base - 10)))             \
     325                 :             add_num = 10 + (end - local_let_high);                      \
     326                 :           else                                                          \
     327                 :             break;                                                      \
     328                 :         }                                                               \
     329                 :         else                                                            \
     330                 :         {                                                               \
     331                 :           if (scan < (char)0x30) break;                                 \
     332                 :                                                                         \
     333                 :           if (scan <= ascii_num_end)                                    \
     334                 :             add_num = (scan - (char)0x30);                              \
     335                 :           else if (num_base <= 10)                                      \
     336                 :             break;                                                      \
     337                 :           else if ((scan >= (char)0x41) && (scan <= ascii_let_high_end)) \
     338                 :             add_num = 10 + (scan - (char)0x41);                         \
     339                 :           else if ((scan >= 0x61) && (scan <= ascii_let_low_end))       \
     340                 :             add_num = 10 + (scan - (char)0x61);                         \
     341                 :           else                                                          \
     342                 :             break;                                                      \
     343                 :         }                                                               \
     344                 : 
     345                 : #define VSTR__PARSE_NUM_LOOP_END()                                      \
     346                 :         --len;                                                          \
     347                 :         done_once = TRUE;                                               \
     348                 :       }                                                                 \
     349                 : } while (FALSE)
     350                 : 
     351                 : /* assume negative numbers can be one bigger than signed positive numbers */
     352                 : #define VSTR__PARSE_NUM_END_S(num_max) do {                     \
     353                 :       if ((flags & VSTR_FLAG_PARSE_NUM_OVERFLOW) &&             \
     354                 :           ((ret - is_neg) > num_max))                           \
     355                 :       {                                                         \
     356                 :         *err = VSTR_TYPE_PARSE_NUM_ERR_OVERFLOW;                \
     357                 :         ret = num_max + is_neg;                                 \
     358                 :       }                                                         \
     359                 :       if (len && !*err) *err = VSTR_TYPE_PARSE_NUM_ERR_OOB;     \
     360                 :                                                                 \
     361                 :      ret_num_len:                                               \
     362                 :       if (ret_len)                                              \
     363                 :         *ret_len = (orig_len - len);                            \
     364                 :                                                                 \
     365                 :       if (is_neg)                                               \
     366                 :         return (-ret);                                          \
     367                 :                                                                 \
     368                 :       return (ret);                                             \
     369                 :     } while (FALSE)
     370                 : 
     371                 : #define VSTR__PARSE_NUM_END_U() do {                            \
     372                 :       if (len && !*err) *err = VSTR_TYPE_PARSE_NUM_ERR_OOB;     \
     373                 :                                                                 \
     374                 :      ret_num_len:                                               \
     375                 :       if (ret_len)                                              \
     376                 :         *ret_len = (orig_len - len);                            \
     377                 :                                                                 \
     378                 :       return (ret);                                             \
     379                 :     } while (FALSE)
     380                 : 
     381                 : #define VSTR__PARSE_NUM_SFUNC(num_type, num_max) do { \
     382                 :       VSTR__PARSE_NUM_BEG_S(num_type);                \
     383                 :       VSTR__PARSE_NUM_ASCII();                        \
     384                 :       VSTR__PARSE_NUM_LOOP_BEG();                     \
     385                 :       VSTR__PARSE_NUM_BIN_CALC_NUM(num_type);         \
     386                 :       VSTR__PARSE_NUM_LOOP_END();                     \
     387                 :       VSTR__PARSE_NUM_END_S(num_max);                 \
     388                 :     } while (FALSE)
     389                 : 
     390                 : #define VSTR__PARSE_NUM_UFUNC(num_type) do {  \
     391                 :       VSTR__PARSE_NUM_BEG_U(num_type);        \
     392                 :       VSTR__PARSE_NUM_ASCII();                \
     393                 :       VSTR__PARSE_NUM_LOOP_BEG();             \
     394                 :       VSTR__PARSE_NUM_BIN_CALC_NUM(num_type); \
     395                 :       VSTR__PARSE_NUM_LOOP_END();             \
     396                 :       VSTR__PARSE_NUM_END_U();                \
     397                 :     } while (FALSE)
     398                 : 
     399                 : void *vstr_parse_num(const Vstr_base *base, size_t pos, size_t len,
     400                 :                      unsigned int flags, size_t *ret_len,
     401                 :                      unsigned int *err,
     402                 :                      void *(*func)(unsigned int, int, unsigned int *, void *),
     403                 :                      void *data)
     404             130 : {
     405             130 :   VSTR__PARSE_NUM_BEG_S(void *);
     406             130 :   ret = data;
     407             130 :   VSTR__PARSE_NUM_ASCII();
     408             130 :   VSTR__PARSE_NUM_LOOP_BEG();
     409                 : 
     410             620 :   if (is_neg) add_num = -add_num;
     411                 :   
     412             620 :   if (!(ret = func(num_base, add_num, err, ret)) && !*err)
     413              10 :     return (NULL); /* mem error */
     414                 :   
     415             610 :   VSTR__PARSE_NUM_LOOP_END();
     416             120 :   VSTR__PARSE_NUM_END_U();
     417                 : }
     418                 : 
     419                 : short vstr_parse_short(const Vstr_base *base, size_t pos, size_t len,
     420                 :                        unsigned int flags, size_t *ret_len,
     421                 :                        unsigned int *err)
     422             100 : { VSTR__PARSE_NUM_SFUNC(unsigned short, SHRT_MAX); }
     423                 : 
     424                 : unsigned short vstr_parse_ushort(const Vstr_base *base,
     425                 :                                  size_t pos, size_t len,
     426                 :                                  unsigned int flags, size_t *ret_len,
     427                 :                                  unsigned int *err)
     428             536 : { VSTR__PARSE_NUM_UFUNC(unsigned short); }
     429                 : 
     430                 : int vstr_parse_int(const Vstr_base *base, size_t pos, size_t len,
     431                 :                    unsigned int flags, size_t *ret_len, unsigned int *err)
     432              90 : { VSTR__PARSE_NUM_SFUNC(unsigned int, INT_MAX); }
     433                 : 
     434                 : unsigned int vstr_parse_uint(const Vstr_base *base, size_t pos, size_t len,
     435                 :                              unsigned int flags, size_t *ret_len,
     436                 :                              unsigned int *err)
     437           33213 : { VSTR__PARSE_NUM_UFUNC(unsigned int); }
     438                 : 
     439                 : long vstr_parse_long(const Vstr_base *base, size_t pos, size_t len,
     440                 :                      unsigned int flags, size_t *ret_len,
     441                 :                      unsigned int *err)
     442              10 : { VSTR__PARSE_NUM_SFUNC(unsigned long, LONG_MAX); }
     443                 : 
     444                 : unsigned long vstr_parse_ulong(const Vstr_base *base, size_t pos, size_t len,
     445                 :                                unsigned int flags, size_t *ret_len,
     446                 :                                unsigned int *err)
     447            6397 : { VSTR__PARSE_NUM_UFUNC(unsigned long); }
     448                 : 
     449                 : intmax_t vstr_parse_intmax(const struct Vstr_base *base,
     450                 :                            size_t pos, size_t len,
     451                 :                            unsigned int flags, size_t *ret_len,
     452                 :                            unsigned int *err)
     453              25 : { VSTR__PARSE_NUM_SFUNC(uintmax_t, INTMAX_MAX); }
     454                 : 
     455                 : uintmax_t vstr_parse_uintmax(const struct Vstr_base *base,
     456                 :                              size_t pos, size_t len,
     457                 :                              unsigned int flags, size_t *ret_len,
     458                 :                              unsigned int *err)
     459            5362 : { VSTR__PARSE_NUM_UFUNC(uintmax_t); }
     460                 : 
     461                 : static int vstr__parse_ipv4_netmask(const struct Vstr_base *base,
     462                 :                                     size_t pos, size_t *passed_len,
     463                 :                                     unsigned int flags,
     464                 :                                     unsigned int num_flags,
     465                 :                                     char sym_dot,
     466                 :                                     unsigned int *cidr, unsigned int *err)
     467                 : {
     468             105 :   int zero_rest = FALSE;
     469             105 :   size_t len = *passed_len;
     470             105 :   unsigned int scan = 0;
     471                 : 
     472             380 :   while (len)
     473                 :   {
     474             360 :     unsigned int tmp = 0;
     475             360 :     size_t num_len = 3;
     476                 : 
     477             360 :     if (num_len > len)
     478              30 :       num_len = len;
     479                 : 
     480             360 :     tmp = vstr_parse_uint(base, pos, num_len, 10 | num_flags,
     481                 :                           &num_len, NULL);
     482             360 :     if (!num_len)
     483               5 :       break;
     484                 : 
     485             355 :     pos += num_len;
     486             355 :     len -= num_len;
     487                 : 
     488             355 :     if (zero_rest && tmp)
     489                 :     {
     490               5 :       *err = VSTR_TYPE_PARSE_IPV4_ERR_NETMASK_OOB;
     491               5 :       return (FALSE);
     492                 :     }
     493             350 :     else if (!zero_rest)
     494                 :     {
     495             335 :       if (tmp > 255)
     496                 :       {
     497               5 :         *err = VSTR_TYPE_PARSE_IPV4_ERR_NETMASK_OOB;
     498               5 :         return (FALSE);
     499                 :       }
     500                 : 
     501             330 :       if (tmp != 255)
     502                 :       {
     503              75 :         *cidr = scan * 8;
     504              75 :         switch (tmp)
     505                 :         {
     506                 :           default:
     507               5 :             *err = VSTR_TYPE_PARSE_IPV4_ERR_NETMASK_OOB;
     508               5 :             return (FALSE);
     509                 : 
     510               5 :           case 254: *cidr += 7; break;
     511               5 :           case 252: *cidr += 6; break;
     512               5 :           case 248: *cidr += 5; break;
     513               5 :           case 240: *cidr += 4; break;
     514               5 :           case 224: *cidr += 3; break;
     515              20 :           case 192: *cidr += 2; break;
     516              25 :           case 128: *cidr += 1; break;
     517              70 :           case   0:             break;
     518                 :         }
     519              70 :         zero_rest = TRUE;
     520                 :       }
     521                 :     }
     522                 : 
     523             340 :     ++scan;
     524                 : 
     525             340 :     if (scan == 4)
     526              60 :       break;
     527                 : 
     528             280 :     if (len && (vstr_export_chr(base, pos) != sym_dot))
     529               5 :       break;
     530                 : 
     531             275 :     if (len)
     532                 :     { /* skip the dot */
     533             265 :       ++pos;
     534             265 :       --len;
     535                 :     }
     536                 :   }
     537              90 :   if (!zero_rest)
     538              25 :     *cidr = scan * 8;
     539                 :   
     540              90 :   if ((flags & VSTR_FLAG_PARSE_IPV4_NETMASK_FULL) && (scan != 4))
     541                 :   {
     542              10 :     *err = VSTR_TYPE_PARSE_IPV4_ERR_NETMASK_FULL;
     543              10 :     return (FALSE);
     544                 :   }
     545                 : 
     546              80 :   *passed_len = len;
     547                 : 
     548              80 :   return (TRUE);
     549                 : }
     550                 : 
     551                 : static int vstr__parse_ipv4_cidr(const struct Vstr_base *base,
     552                 :                                  size_t pos, size_t *passed_len,
     553                 :                                  unsigned int flags,
     554                 :                                  unsigned int num_flags,
     555                 :                                  char sym_dot,
     556                 :                                  unsigned int *cidr, unsigned int *err)
     557             105 : {
     558             105 :   size_t len = *passed_len;
     559             105 :   size_t num_len = 0;
     560                 : 
     561             105 :   if (len)
     562              95 :     *cidr = vstr_parse_uint(base, pos, len, 10 | num_flags,
     563                 :                             &num_len, NULL);
     564             105 :   if (num_len)
     565                 :   {
     566              95 :     if ((flags & VSTR_FLAG_PARSE_IPV4_NETMASK) &&
     567                 :         (*cidr > 32) && (len > num_len) &&
     568                 :         (vstr_export_chr(base, pos + num_len) == sym_dot))
     569                 :     {
     570              70 :       if (!vstr__parse_ipv4_netmask(base, pos, &len, flags, num_flags,
     571                 :                                     sym_dot, cidr, err))
     572              10 :         return (FALSE);
     573                 :     }
     574              25 :     else if (*cidr <= 32)
     575                 :     {
     576              20 :       pos += num_len;
     577              20 :       len -= num_len;
     578                 :     }
     579                 :     else
     580                 :     {
     581               5 :       *err = VSTR_TYPE_PARSE_IPV4_ERR_CIDR_OOB;
     582               5 :       return (FALSE);
     583                 :     }
     584                 :   }
     585              10 :   else if (flags & VSTR_FLAG_PARSE_IPV4_CIDR_FULL)
     586                 :   {
     587               5 :     *err = VSTR_TYPE_PARSE_IPV4_ERR_CIDR_FULL;
     588               5 :     return (FALSE);
     589                 :   }
     590                 :   else
     591               5 :     *cidr = 32;
     592                 : 
     593              85 :   *passed_len = len;
     594                 : 
     595              85 :   return (TRUE);
     596                 : }
     597                 : 
     598                 : int vstr_parse_ipv4(const struct Vstr_base *base,
     599                 :                     size_t pos, size_t len,
     600                 :                     unsigned char *ips, unsigned int *cidr,
     601                 :                     unsigned int flags, size_t *ret_len, unsigned int *err)
     602             270 : {
     603             270 :   size_t orig_len = len;
     604             270 :   char sym_slash = 0x2F;
     605             270 :   char sym_dot = 0x2E;
     606             270 :   unsigned int num_flags = VSTR_FLAG_PARSE_NUM_NO_BEG_PM;
     607             270 :   unsigned int scan = 0;
     608             270 :   unsigned int dummy_err = 0;
     609                 : 
     610             270 :   assert(ips);
     611                 : 
     612             270 :   if (ret_len) *ret_len = 0;
     613             270 :   if (!err)
     614              70 :     err = &dummy_err;
     615                 : 
     616             270 :   *err = 0;
     617                 : 
     618             270 :   if (flags & VSTR_FLAG_PARSE_IPV4_LOCAL)
     619                 :   {
     620              20 :     num_flags |= VSTR_FLAG_PARSE_NUM_LOCAL;
     621              20 :     sym_slash = '/';
     622              20 :     sym_dot = '.';
     623                 :   }
     624                 : 
     625             270 :   if (!(flags & VSTR_FLAG_PARSE_IPV4_ZEROS))
     626             265 :     num_flags |= VSTR_FLAG_PARSE_NUM_NO_BEG_ZERO;
     627                 : 
     628             995 :   while (len)
     629                 :   {
     630             990 :     unsigned int tmp = 0;
     631             990 :     size_t num_len = 3;
     632                 : 
     633             990 :     if (num_len > len)
     634              85 :       num_len = len;
     635                 : 
     636             990 :     tmp = vstr_parse_uint(base, pos, num_len, 10 | num_flags,
     637                 :                           &num_len, NULL);
     638             990 :     if (!num_len)
     639              15 :       break;
     640                 : 
     641             975 :     if (tmp > 255)
     642                 :     {
     643               5 :       *err = VSTR_TYPE_PARSE_IPV4_ERR_IPV4_OOB;
     644               5 :       return (FALSE);
     645                 :     }
     646                 : 
     647             970 :     pos += num_len;
     648             970 :     len -= num_len;
     649                 : 
     650             970 :     ips[scan++] = tmp;
     651                 : 
     652             970 :     if (scan == 4)
     653             225 :       break;
     654                 : 
     655             745 :     if (len && (vstr_export_chr(base, pos) == sym_slash))
     656              10 :       break;
     657                 : 
     658             735 :     if (len && (vstr_export_chr(base, pos) != sym_dot))
     659              10 :       break;
     660                 : 
     661             725 :     if (len)
     662                 :     { /* skip the dot */
     663             720 :       ++pos;
     664             720 :       --len;
     665                 :     }
     666                 : 
     667             725 :     if (len && (vstr_export_chr(base, pos) == sym_slash))
     668             265 :       break;
     669                 :   }
     670                 : 
     671             265 :   if ((scan != 4) && (flags & VSTR_FLAG_PARSE_IPV4_FULL))
     672                 :   {
     673              20 :     *err = VSTR_TYPE_PARSE_IPV4_ERR_IPV4_FULL;
     674              20 :     return (FALSE);
     675                 :   }
     676                 : 
     677             285 :   while (scan < 4)
     678              40 :     ips[scan++] = 0;
     679                 : 
     680             245 :   if (cidr)
     681             185 :     *cidr = 32;
     682                 : 
     683             245 :   if (len && (vstr_export_chr(base, pos) == sym_slash))
     684                 :   {
     685             160 :     if (flags & VSTR_FLAG_PARSE_IPV4_CIDR)
     686                 :     {
     687             105 :       ++pos;
     688             105 :       --len;
     689                 : 
     690             105 :       if (!vstr__parse_ipv4_cidr(base, pos, &len, flags, num_flags, sym_dot,
     691                 :                                  cidr, err))
     692              20 :         return (FALSE);
     693                 :     }
     694              55 :     else if (flags & VSTR_FLAG_PARSE_IPV4_NETMASK)
     695                 :     {
     696              35 :       ++pos;
     697              35 :       --len;
     698                 : 
     699              35 :       if (!vstr__parse_ipv4_netmask(base, pos, &len, flags, num_flags, sym_dot,
     700                 :                                     cidr, err))
     701              15 :         return (FALSE);
     702                 :     }
     703                 :   }
     704                 : 
     705             210 :   if (len && (flags & VSTR_FLAG_PARSE_IPV4_ONLY))
     706              20 :     *err = VSTR_TYPE_PARSE_IPV4_ERR_ONLY;
     707                 : 
     708             210 :   if (ret_len)
     709             210 :     *ret_len = orig_len - len;
     710                 : 
     711             210 :   return (TRUE);
     712                 : }
     713                 : 
     714                 : static int vstr__parse_ipv6_cidr(const struct Vstr_base *base,
     715                 :                                  size_t pos, size_t *passed_len,
     716                 :                                  unsigned int flags,
     717                 :                                  unsigned int num_flags,
     718                 :                                  unsigned int *cidr, unsigned int *err)
     719             110 : {
     720             110 :   size_t len = *passed_len;
     721             110 :   size_t num_len = 0;
     722                 : 
     723             110 :   if (len)
     724              90 :     *cidr = vstr_parse_uint(base, pos, len, 10 | num_flags,
     725                 :                             &num_len, NULL);
     726             110 :   if (num_len)
     727                 :   {
     728              90 :     if (*cidr <= 128)
     729                 :     {
     730              80 :       pos += num_len;
     731              80 :       len -= num_len;
     732                 :     }
     733                 :     else
     734                 :     {
     735              10 :       *err = VSTR_TYPE_PARSE_IPV6_ERR_CIDR_OOB;
     736              10 :       return (FALSE);
     737                 :     }
     738                 :   }
     739              20 :   else if (flags & VSTR_FLAG_PARSE_IPV6_CIDR_FULL)
     740                 :   {
     741              10 :     *err = VSTR_TYPE_PARSE_IPV6_ERR_CIDR_FULL;
     742              10 :     return (FALSE);
     743                 :   }
     744                 :   else
     745              10 :     *cidr = 128;
     746                 : 
     747              90 :   *passed_len = len;
     748                 : 
     749              90 :   return (TRUE);
     750                 : }
     751                 : 
     752                 : /* see rfc 2373 */
     753                 : /*
     754                 :  *   1. 1 to 4 hexdigits in 8 groups: hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh
     755                 :  *                                    h:h:h:h:h:h:h:h
     756                 :  *   2. Any number of 0000 may be abbreviated as "::", but only once
     757                 :  *   3. Note this means that "::" is a valid ipv6 address (all zeros)
     758                 :  *   4. The last two words may be written as an IPv4 address ::1234:127.0.0.1
     759                 :  */
     760                 : int vstr_parse_ipv6(const struct Vstr_base *base,
     761                 :                     size_t pos, size_t len,
     762                 :                     unsigned int *ips, unsigned int *cidr,
     763                 :                     unsigned int flags, size_t *ret_len, unsigned int *err)
     764             310 : {
     765             310 :   size_t orig_len = len;
     766             310 :   char sym_slash = 0x2F;
     767             310 :   char sym_colon = 0x3a;
     768             310 :   unsigned int num_flags = VSTR_FLAG_PARSE_NUM_NO_BEG_PM;
     769             310 :   unsigned int scan = 0;
     770             310 :   unsigned int dummy_err = 0;
     771             310 :   unsigned int off_null = 0;
     772             310 :   VSTR_SECTS_DECL(sects, 8);
     773             310 :   size_t num_len = 0;
     774                 : 
     775             310 :   VSTR_SECTS_DECL_INIT(sects);
     776                 : 
     777             310 :   assert(ips);
     778             310 :   vstr_wrap_memset(ips, 0, sizeof(int) * 8);
     779                 : 
     780             310 :   if (ret_len) *ret_len = 0;
     781             310 :   if (!err)
     782             155 :     err = &dummy_err;
     783                 : 
     784             310 :   *err = 0;
     785                 : 
     786             310 :   if (len < 2)
     787                 :   {
     788              10 :     *err = VSTR_TYPE_PARSE_IPV6_ERR_IPV6_FULL;
     789              10 :     return (FALSE);
     790                 :   }
     791                 : 
     792             300 :   if (flags & VSTR_FLAG_PARSE_IPV6_LOCAL)
     793                 :   {
     794              20 :     num_flags |= VSTR_FLAG_PARSE_NUM_LOCAL;
     795              20 :     sym_slash = '/';
     796              20 :     sym_colon = ':';
     797                 :   }
     798                 : 
     799                 :   {
     800             300 :     const int split_flags = (VSTR_FLAG_SPLIT_MID_NULL | VSTR_FLAG_SPLIT_NO_RET);
     801             300 :     char buf[2]; buf[0] = sym_colon; buf[1] = sym_colon;
     802                 : 
     803             300 :     if (VSTR_CMP_BUF_EQ(base, pos, 2, buf, 2))
     804              70 :       vstr_sects_add(sects, pos, 0);
     805                 : 
     806             300 :     vstr_split_buf(base, pos, len, buf, 1, sects, sects->sz, split_flags);
     807                 :   }
     808                 : 
     809            1570 :   while (scan < sects->num)
     810                 :   {
     811            1340 :     unsigned int tmp = 0;
     812                 : 
     813            1340 :     ++scan;
     814            1340 :     if (!VSTR_SECTS_NUM(sects, scan)->len)
     815                 :     {
     816             220 :       if (off_null)
     817                 :       {
     818              10 :         *err = VSTR_TYPE_PARSE_IPV6_ERR_IPV6_NULL;
     819              10 :         return (FALSE);
     820                 :       }
     821                 : 
     822             210 :       off_null = scan;
     823             210 :       ips[scan - 1] = 0;
     824             210 :       continue;
     825                 :     }
     826                 : 
     827            1120 :     tmp = vstr_parse_uint(base,
     828                 :                           VSTR_SECTS_NUM(sects, scan)->pos,
     829                 :                           VSTR_SECTS_NUM(sects, scan)->len, 16 | num_flags,
     830                 :                           &num_len, NULL);
     831            1120 :     if (!num_len && off_null && (off_null == (scan - 1)) &&
     832                 :         (scan == sects->num))
     833              50 :       break;
     834                 : 
     835            1070 :     if ((num_len > 4) || !num_len || (tmp > 0xFFFF))
     836                 :     {
     837              10 :       *err = VSTR_TYPE_PARSE_IPV6_ERR_IPV6_OOB;
     838              10 :       return (FALSE);
     839                 :     }
     840                 : 
     841            1060 :     ips[scan - 1] = tmp;
     842                 :   }
     843                 : 
     844             280 :   len -= VSTR_SECTS_NUM(sects, scan)->pos - pos;
     845             280 :   pos = VSTR_SECTS_NUM(sects, scan)->pos;
     846             280 :   if (scan != 8)
     847                 :   {
     848             230 :     ASSERT(scan < 8);
     849                 : 
     850             230 :     if ((VSTR_SECTS_NUM(sects, scan)->len > 4) && (off_null || (scan == 7)))
     851                 :     { /* try an ipv4 address at the end... */
     852              70 :       unsigned char ipv4_ips[4];
     853              70 :       unsigned int ipv4_flags = VSTR_FLAG_PARSE_IPV4_FULL;
     854              70 :       size_t tmp_num_len = 0;
     855                 : 
     856              70 :       if (flags & VSTR_FLAG_PARSE_IPV6_LOCAL)
     857              10 :         ipv4_flags |= VSTR_FLAG_PARSE_IPV4_LOCAL;
     858                 : 
     859              70 :       ASSERT(off_null != scan);
     860                 : 
     861              70 :       if (vstr_parse_ipv4(base,
     862                 :                           VSTR_SECTS_NUM(sects, scan)->pos,
     863                 :                           VSTR_SECTS_NUM(sects, scan)->len,
     864                 :                           ipv4_ips, NULL, ipv4_flags, &tmp_num_len, NULL))
     865                 :       {
     866              60 :         num_len = tmp_num_len;
     867              60 :         ips[scan - 1] = ipv4_ips[1] + (((unsigned int)ipv4_ips[0]) << 8);
     868              60 :         ips[scan++]   = ipv4_ips[3] + (((unsigned int)ipv4_ips[2]) << 8);
     869                 :       }
     870                 :     }
     871             230 :     if (scan != 8 && !off_null)
     872                 :     {
     873              10 :       *err = VSTR_TYPE_PARSE_IPV6_ERR_IPV6_FULL;
     874              10 :       return (FALSE);
     875                 :     }
     876                 : 
     877             220 :     if (off_null != scan) /* don't have to do anything for ends with :: */
     878                 :     {
     879             220 :       unsigned int *beg = ips + off_null;
     880             220 :       unsigned int off_end = (8 - scan);
     881             220 :       unsigned int num = (scan - off_null);
     882                 : 
     883             220 :       vstr_wrap_memmove(beg + off_end, beg, num * sizeof(unsigned int));
     884             220 :       vstr_wrap_memset(beg, 0, off_end * sizeof(unsigned int));
     885                 :     }
     886                 :   }
     887                 : 
     888             270 :   ASSERT(len >= num_len);
     889             270 :   pos += num_len;
     890             270 :   len -= num_len;
     891             270 :   if (cidr)
     892             270 :     *cidr = 128;
     893                 : 
     894             270 :   if (len && (vstr_export_chr(base, pos) == sym_slash))
     895                 :   {
     896             160 :     if (flags & VSTR_FLAG_PARSE_IPV6_CIDR)
     897                 :     {
     898             110 :       ++pos;
     899             110 :       --len;
     900                 : 
     901             110 :       if (!vstr__parse_ipv6_cidr(base, pos, &len, flags, num_flags, cidr, err))
     902              20 :         return (FALSE);
     903                 :     }
     904                 :   }
     905                 : 
     906             250 :   if (len && (flags & VSTR_FLAG_PARSE_IPV6_ONLY))
     907              10 :     *err = VSTR_TYPE_PARSE_IPV6_ERR_ONLY;
     908                 : 
     909             250 :   if (ret_len)
     910             250 :     *ret_len = orig_len - len;
     911                 : 
     912             250 :   return (TRUE);
     913                 : }

Generated by: LTP GCOV extension version 1.1