]> git.sur5r.net Git - openldap/blobdiff - libraries/librewrite/subst.c
ITS#8585 Fail ldap_result if handle is already bad
[openldap] / libraries / librewrite / subst.c
index 6aafac51180535106b44d7ee999b373d75b9ee27..8efed1422090277d06a2b4428ec6d51e59c39088 100644 (file)
@@ -1,26 +1,21 @@
-/******************************************************************************
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright (C) 2000 Pierangelo Masarati, <ando@sys-net.it>
+ * Copyright 2000-2017 The OpenLDAP Foundation.
  * All rights reserved.
  *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to alter it and redistribute it, subject
- * to the following restrictions:
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
  *
- * 1. The author is not responsible for the consequences of use of this
- * software, no matter how awful, even if they arise from flaws in it.
- *
- * 2. The origin of this software must not be misrepresented, either by
- * explicit claim or by omission.  Since few users ever read sources,
- * credits should appear in the documentation.
- *
- * 3. Altered versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.  Since few users
- * ever read sources, credits should appear in the documentation.
- * 
- * 4. This notice may not be removed or altered.
- *
- ******************************************************************************/
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENT:
+ * This work was initially developed by Pierangelo Masarati for
+ * inclusion in OpenLDAP Software.
+ */
 
 #include <portable.h>
 
@@ -32,7 +27,7 @@
 struct rewrite_subst *
 rewrite_subst_compile(
                struct rewrite_info *info,
-               const char *result
+               const char *str
 )
 {
        size_t subs_len;
@@ -41,35 +36,39 @@ rewrite_subst_compile(
 
        struct rewrite_subst *s = NULL;
 
-       const char *begin, *p;
+       char *result, *begin, *p;
        int nsub = 0, l;
 
        assert( info != NULL );
-       assert( result != NULL );
+       assert( str != NULL );
+
+       result = strdup( str );
+       if ( result == NULL ) {
+               return NULL;
+       }
 
        /*
         * Take care of substitution string
         */
        for ( p = begin = result, subs_len = 0; p[ 0 ] != '\0'; p++ ) {
-               
+
                /*
                 * Keep only single escapes '%'
                 */
-               if ( p[ 0 ] != REWRITE_SUBMATCH_ESCAPE ) {
+               if (  !IS_REWRITE_SUBMATCH_ESCAPE( p[ 0 ] ) ) {
                        continue;
                } 
 
-               if ( p[ 1 ] == REWRITE_SUBMATCH_ESCAPE ) {
+               if (  IS_REWRITE_SUBMATCH_ESCAPE( p[ 1 ] ) ) {
                        /* Pull &p[1] over p, including the trailing '\0' */
                        AC_MEMCPY((char *)p, &p[ 1 ], strlen( p ) );
                        continue;
                }
 
-               tmps = (struct berval *)realloc( subs,
+               tmps = ( struct berval * )realloc( subs,
                                sizeof( struct berval )*( nsub + 1 ) );
                if ( tmps == NULL ) {
-                       /* FIXME: cleanup */
-                       return NULL;
+                       goto cleanup;
                }
                subs = tmps;
                
@@ -83,7 +82,7 @@ rewrite_subst_compile(
                        subs[ nsub ].bv_len = l;
                        subs[ nsub ].bv_val = malloc( l + 1 );
                        if ( subs[ nsub ].bv_val == NULL ) {
-                               return NULL;
+                               goto cleanup;
                        }
                        AC_MEMCPY( subs[ nsub ].bv_val, begin, l );
                        subs[ nsub ].bv_val[ l ] = '\0';
@@ -96,17 +95,17 @@ rewrite_subst_compile(
                 * Substitution pattern
                 */
                if ( isdigit( (unsigned char) p[ 1 ] ) ) {
-                       int d = p[ 1 ] - '0';
                        struct rewrite_submatch *tmpsm;
+                       int d = p[ 1 ] - '0';
 
                        /*
                         * Add a new value substitution scheme
                         */
-                       tmpsm = realloc( submatch, 
-       sizeof( struct rewrite_submatch )*( nsub + 1 ) );
+
+                       tmpsm = ( struct rewrite_submatch * )realloc( submatch,
+                                       sizeof( struct rewrite_submatch )*( nsub + 1 ) );
                        if ( tmpsm == NULL ) {
-                               /* cleanup */
-                               return NULL;
+                               goto cleanup;
                        }
                        submatch = tmpsm;
                        submatch[ nsub ].ls_submatch = d;
@@ -118,7 +117,9 @@ rewrite_subst_compile(
                        if ( p[ 2 ] != '{' ) {
                                submatch[ nsub ].ls_type = 
                                        REWRITE_SUBMATCH_ASIS;
+                               submatch[ nsub ].ls_map = NULL;
                                begin = ++p + 1;
+
                        } else {
                                struct rewrite_map *map;
 
@@ -126,14 +127,12 @@ rewrite_subst_compile(
                                        REWRITE_SUBMATCH_XMAP;
 
                                map = rewrite_xmap_parse( info,
-                                               p + 3, &begin );
+                                               p + 3, (const char **)&begin );
                                if ( map == NULL ) {
-                                       /* cleanup */
-                                       return NULL;
+                                       goto cleanup;
                                }
-                               p = begin - 1;
-
                                submatch[ nsub ].ls_map = map;
+                               p = begin - 1;
                        }
 
                /*
@@ -143,27 +142,36 @@ rewrite_subst_compile(
                        struct rewrite_map *map;
                        struct rewrite_submatch *tmpsm;
 
-                       map = rewrite_map_parse( info, p + 2, &begin );
+                       map = rewrite_map_parse( info, p + 2,
+                                       (const char **)&begin );
                        if ( map == NULL ) {
-                               /* cleanup */
-                               return NULL;
+                               goto cleanup;
                        }
                        p = begin - 1;
 
                        /*
                         * Add a new value substitution scheme
                         */
-                       tmpsm = realloc( submatch,
+                       tmpsm = ( struct rewrite_submatch * )realloc( submatch,
                                        sizeof( struct rewrite_submatch )*( nsub + 1 ) );
                        if ( tmpsm == NULL ) {
-                               /* cleanup */
-                               return NULL;
+                               rewrite_map_destroy( &map );
+                               goto cleanup;
                        }
                        submatch = tmpsm;
                        submatch[ nsub ].ls_type =
                                REWRITE_SUBMATCH_MAP_W_ARG;
-                       
                        submatch[ nsub ].ls_map = map;
+
+               /*
+                * Escape '%' ...
+                */
+               } else if ( p[ 1 ] == '%' ) {
+                       AC_MEMCPY( &p[ 1 ], &p[ 2 ], strlen( &p[ 1 ] ) );
+                       continue;
+
+               } else {
+                       goto cleanup;
                }
 
                nsub++;
@@ -172,21 +180,23 @@ rewrite_subst_compile(
        /*
         * Last part of string
         */
-       tmps = realloc( subs, sizeof( struct berval )*( nsub + 1 ) );
+       tmps = (struct berval * )realloc( subs, sizeof( struct berval )*( nsub + 1 ) );
        if ( tmps == NULL ) {
                /*
                 * XXX need to free the value subst stuff!
                 */
-               free( submatch );
-               return NULL;
+               free( subs );
+               goto cleanup;
        }
-
        subs = tmps;
        l = p - begin;
        if ( l > 0 ) {
                subs_len += l;
                subs[ nsub ].bv_len = l;
                subs[ nsub ].bv_val = malloc( l + 1 );
+               if ( subs[ nsub ].bv_val == NULL ) {
+                       goto cleanup;
+               }
                AC_MEMCPY( subs[ nsub ].bv_val, begin, l );
                subs[ nsub ].bv_val[ l ] = '\0';
        } else {
@@ -196,14 +206,30 @@ rewrite_subst_compile(
 
        s = calloc( sizeof( struct rewrite_subst ), 1 );
        if ( s == NULL ) {
-               /* cleanup */
-               return NULL;
+               goto cleanup;
        }
 
        s->lt_subs_len = subs_len;
-        s->lt_subs = subs;
-        s->lt_num_submatch = nsub;
-        s->lt_submatch = submatch;
+       s->lt_subs = subs;
+       s->lt_num_submatch = nsub;
+       s->lt_submatch = submatch;
+       subs = NULL;
+       submatch = NULL;
+
+cleanup:;
+       if ( subs ) {
+               for ( l=0; l<nsub; l++ ) {
+                       free( subs[nsub].bv_val );
+               }
+               free( subs );
+       }
+       if ( submatch ) {
+               for ( l=0; l<nsub; l++ ) {
+                       free( submatch[nsub].ls_map );
+               }
+               free( submatch );
+       }
+       free( result );
 
        return s;
 }
@@ -236,7 +262,7 @@ submatch_copy(
        l = match[ c ].rm_eo - match[ c ].rm_so;
        
        val->bv_len = l;
-       val->bv_val = calloc( sizeof( char ), l + 1 );
+       val->bv_val = malloc( l + 1 );
        if ( val->bv_val == NULL ) {
                return REWRITE_ERR;
        }
@@ -326,7 +352,6 @@ rewrite_subst_apply(
                        }
                        
                        if ( rc != REWRITE_SUCCESS ) {
-                               rc = REWRITE_REGEXEC_ERR;
                                goto cleanup;
                        }
                        break;
@@ -355,12 +380,16 @@ rewrite_subst_apply(
                        rc = rewrite_xmap_apply( info, op,
                                        subst->lt_submatch[ n ].ls_map,
                                        &key, &submatch[ n ] );
+                       free( key.bv_val );
+                       key.bv_val = NULL;
                        break;
                        
                case REWRITE_SUBMATCH_MAP_W_ARG:
                        rc = rewrite_map_apply( info, op,
                                        subst->lt_submatch[ n ].ls_map,
                                        &key, &submatch[ n ] );
+                       free( key.bv_val );
+                       key.bv_val = NULL;
                        break;
 
                default:
@@ -373,9 +402,10 @@ rewrite_subst_apply(
                        rc = REWRITE_ERR;
                        break;
                }
-               
+
                if ( rc != REWRITE_SUCCESS ) {
                        rc = REWRITE_REGEXEC_ERR;
+                       goto cleanup;
                }
                
                /*
@@ -385,18 +415,17 @@ rewrite_subst_apply(
        }
        
        /*
-         * Alloc result buffer as big as the constant part 
-         * of the subst pattern and initialize it
+         * Alloc result buffer
          */
        l += subst->lt_subs_len;
-       res = calloc( sizeof( char ), l + 1 );
+       res = malloc( l + 1 );
        if ( res == NULL ) {
                rc = REWRITE_REGEXEC_ERR;
                goto cleanup;
        }
 
        /*
-        * Apply submatches (possibly resolved thru maps
+        * Apply submatches (possibly resolved thru maps)
         */
         for ( n = 0, cl = 0; n < subst->lt_num_submatch; n++ ) {
                if ( subst->lt_subs[ n ].bv_val != NULL ) {
@@ -411,7 +440,9 @@ rewrite_subst_apply(
        if ( subst->lt_subs[ n ].bv_val != NULL ) {
                AC_MEMCPY( res + cl, subst->lt_subs[ n ].bv_val,
                                subst->lt_subs[ n ].bv_len );
+               cl += subst->lt_subs[ n ].bv_len;
        }
+       res[ cl ] = '\0';
 
        val->bv_val = res;
        val->bv_len = l;
@@ -440,8 +471,8 @@ rewrite_subst_destroy(
        int                     n;
        struct rewrite_subst    *subst;
 
-       assert( psubst );
-       assert( *psubst );
+       assert( psubst != NULL );
+       assert( *psubst != NULL );
 
        subst = *psubst;
 
@@ -468,12 +499,18 @@ rewrite_subst_destroy(
                }
        }
 
+       free( subst->lt_submatch );
+       subst->lt_submatch = NULL;
+
        /* last one */
        if ( subst->lt_subs[ n ].bv_val ) {
                free( subst->lt_subs[ n ].bv_val );
                subst->lt_subs[ n ].bv_val = NULL;
        }
 
+       free( subst->lt_subs );
+       subst->lt_subs = NULL;
+
        free( subst );
        *psubst = NULL;