]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/mods.c
Fix one time memory leaks
[openldap] / servers / slapd / mods.c
index 3ba189856a14dfc7a104208bc335f08b3b6581b3..f1dbdffcb804468ef7db1ad83b7d3e8358aeeae0 100644 (file)
@@ -1,7 +1,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 1998-2005 The OpenLDAP Foundation.
+ * Copyright 1998-2006 The OpenLDAP Foundation.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -28,6 +28,7 @@
 #include <ac/string.h>
 
 #include "slap.h"
+#include "lutil.h"
 
 int
 modify_add_values(
@@ -73,11 +74,15 @@ modify_add_values(
                }
 
                if ( permissive ) {
-                       for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) /* count 'em */;
-                       pmod.sm_values = (BerVarray)ch_malloc( (i + 1)*sizeof( struct berval ) );
+                       for ( i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) {
+                               /* EMPTY -- just counting 'em */;
+                       }
+
+                       pmod.sm_values = (BerVarray)ch_malloc(
+                               (i + 1) * sizeof( struct berval ));
                        if ( pmod.sm_nvalues != NULL ) {
                                pmod.sm_nvalues = (BerVarray)ch_malloc(
-                                       (i + 1)*sizeof( struct berval ) );
+                                       (i + 1) * sizeof( struct berval ));
                        }
                }
 
@@ -90,7 +95,7 @@ modify_add_values(
                for ( p = i = 0; !BER_BVISNULL( &mod->sm_values[i] ); i++ ) {
                        int     match;
 
-                       assert( a->a_vals[0].bv_val );
+                       assert( a->a_vals[0].bv_val != NULL );
                        for ( j = 0; !BER_BVISNULL( &a->a_vals[j] ); j++ ) {
                                if ( mod->sm_nvalues ) {
                                        rc = ordered_value_match( &match, mod->sm_desc, mr,
@@ -245,7 +250,7 @@ modify_delete_vindex(
                        }
 
                        if( mod->sm_nvalues ) {
-                               assert( a->a_nvals );
+                               assert( a->a_nvals != NULL );
                                rc = ordered_value_match( &match, a->a_desc, mr,
                                        SLAP_MR_EQUALITY | SLAP_MR_VALUE_OF_ASSERTION_SYNTAX
                                                | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH
@@ -334,7 +339,7 @@ modify_delete_vindex(
                        rc = LDAP_NO_SUCH_ATTRIBUTE;
                }
        } else if ( a->a_desc->ad_type->sat_flags & SLAP_AT_ORDERED_VAL ) {
-       /* For an ordered attribute, renumber the value indices */
+               /* For an ordered attribute, renumber the value indices */
                ordered_value_sort( a, 1 );
        }
 
@@ -372,17 +377,30 @@ modify_increment_values(
 
        a = attr_find( e->e_attrs, mod->sm_desc );
        if( a == NULL ) {
-               *text = textbuf;
-               snprintf( textbuf, textlen,
-                       "modify/increment: %s: no such attribute",
-                       mod->sm_desc->ad_cname.bv_val );
-               return LDAP_NO_SUCH_ATTRIBUTE;
+               if ( permissive ) {
+                       Modification modReplace = *mod;
+
+                       modReplace.sm_op = LDAP_MOD_REPLACE;
+
+                       return modify_add_values(e, &modReplace, permissive, text, textbuf, textlen);
+               } else {
+                       *text = textbuf;
+                       snprintf( textbuf, textlen,
+                               "modify/increment: %s: no such attribute",
+                               mod->sm_desc->ad_cname.bv_val );
+                       return LDAP_NO_SUCH_ATTRIBUTE;
+               }
        }
 
        if ( !strcmp( a->a_desc->ad_type->sat_syntax_oid, SLAPD_INTEGER_SYNTAX )) {
                int i;
                char str[sizeof(long)*3 + 2]; /* overly long */
-               long incr = atol( mod->sm_values[0].bv_val );
+               long incr;
+
+               if ( lutil_atol( &incr, mod->sm_values[0].bv_val ) != 0 ) {
+                       *text = "modify/increment: invalid syntax of increment";
+                       return LDAP_INVALID_SYNTAX;
+               }
 
                /* treat zero and errors as a no-op */
                if( incr == 0 ) {
@@ -391,13 +409,18 @@ modify_increment_values(
 
                for( i = 0; !BER_BVISNULL( &a->a_nvals[i] ); i++ ) {
                        char *tmp;
-                       long value = atol( a->a_nvals[i].bv_val );
-                       size_t strln = snprintf( str, sizeof(str), "%ld", value+incr );
+                       long value;
+                       size_t strln;
+                       if ( lutil_atol( &value, a->a_nvals[i].bv_val ) != 0 ) {
+                               *text = "modify/increment: invalid syntax of original value";
+                               return LDAP_INVALID_SYNTAX;
+                       }
+                       strln = snprintf( str, sizeof(str), "%ld", value+incr );
 
                        tmp = SLAP_REALLOC( a->a_nvals[i].bv_val, strln+1 );
                        if( tmp == NULL ) {
                                *text = "modify/increment: reallocation error";
-                               return LDAP_OTHER;;
+                               return LDAP_OTHER;
                        }
                        a->a_nvals[i].bv_val = tmp;
                        a->a_nvals[i].bv_len = strln;
@@ -432,14 +455,16 @@ slap_mod_free(
 
 void
 slap_mods_free(
-    Modifications      *ml )
+    Modifications      *ml,
+    int                        freevals )
 {
        Modifications *next;
 
        for ( ; ml != NULL; ml = next ) {
                next = ml->sml_next;
 
-               slap_mod_free( &ml->sml_mod, 0 );
+               if ( freevals )
+                       slap_mod_free( &ml->sml_mod, 0 );
                free( ml );
        }
 }