Closed Bug 2853 Opened 21 years ago Closed 21 years ago

Removing and adding attribute values gives Perl error

Categories

(Directory :: PerLDAP, defect, P1, major)

Sun
Solaris

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: leif, Assigned: leif)

References

Details

From: Steve East <seast@uswest.net>

In PerLdap 1.1, should:

     $entry->remove("forcefullupdate");
     $entry->addValue("forcefullupdate", "garbage");

be synonymous with:

     $entry->setValue("forcefullupdate", "garbage");

? The former gives me an uninitialised variable warning at Conn.pm line
474. It worked in 1.0. I shifted to using the latter so the question is
academic.
Setting all current Open/Normal to M4.
Clearing "M" field since Directory product is not used for 5.0 specific project
bug metrics and will mess up our queries on milestones.
Status: NEW → ASSIGNED
Priority: P2 → P1
From:
//====== Brett G. Lemoine -=- <bl@incyte.com>


On a database containing only:

        dn: o=Foo Co, c=US
        objectclass: top
        objectclass: organization
        o: Foo Co
        description: Company of Foo

doing:
        $entry->removeValue('description', 'Company of Foo' );
followed by:
        $entry->addValue('description', 'The Foo Company' );
results in:

        Can't use an undefined value as an ARRAY reference at
        /usr/local/lib/perl5/site_perl/Mozilla/LDAP/Entry.pm line 364,
        <IN> chunk 7.

Following the 'removeValue', $entry looks like this:
0  Mozilla::LDAP::Entry=HASH(0x3e9cb0)
   'o' => ARRAY(0x44c080)
      0  'Foo Co'
   'objectclass' => ARRAY(0x445380)
      0  'top'
      1  'organization'

and $self->{"_self_obj)"} like this (from just inside addValue()):
0  Mozilla::LDAP::Entry=HASH(0x42d5dc)
   '__description_save__modified_' => 1
   '_description_deleted_' => 1
   '_description_save_' => ARRAY(0x1c572c)
      0  'Company of Foo'
   '_oc_keyidx_' => 4
   '_oc_numattr_' => 4
   '_oc_order_' => ARRAY(0x3e9cc8)
      0  'objectclass'
      1  'o'
      2  'description'
      3  '_description_save_'
   '_self_obj_' => Mozilla::LDAP::Entry=HASH(0x42d5dc)
      -> REUSED_ADDRESS
   'description' => ARRAY(0x44c0b0)
        empty array
   'dn' => 'o=Foo Co, c=US'
   'o' => ARRAY(0x44c080)
      0  'Foo Co'
   'objectclass' => ARRAY(0x445380)
      0  'top'
      1  'organization'

There's no change to this just before going into the loop:

        364:          foreach (@{$self->{$attr}})
        365:            {

Here's the relevant debugging trace:

 361:         my $nval = $val;
 363:         $nval = normalizeDN($val) if (defined($norm) && $norm);
 364:         foreach (@{$self->{$attr}})
 365:           {
 364:         foreach (@{$self->{$attr}})
 365:           {
 in
$=Mozilla::LDAP::Entry::FETCH('Mozilla::LDAP::Entry=HASH(0x42d5dc)',
'description') from
/usr/local/lib/perl5/site_perl/Mozilla/LDAP/Entry.pm:364
  93:     my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
  95:     return unless defined($self->{$attr});
  96:     return if $self->{"_${attr}_deleted_"};
 out
$=Mozilla::LDAP::Entry::FETCH('Mozilla::LDAP::Entry=HASH(0x42d5dc)',
'description') from
/usr/local/lib/perl5/site_perl/Mozilla/LDAP/Entry.pm:364
 scalar context return from Mozilla::LDAP::Entry::FETCH: undef

Here's where I get confused... what caused it to drop into STORE?

 in
$=Mozilla::LDAP::Entry::STORE('Mozilla::LDAP::Entry=HASH(0x42d5dc)',
'description', 'ARRAY(0x49ec68)') from
/usr/local/lib/perl5/site_perl/Mozilla/LDAP/Entry.pm:364
  63:     my ($self, $attr, $val) = ($_[$[], lc $_[$[ + 1], $_[$[ + 2]);
  65:     return unless (defined($val) && ($val ne ""));
  66:     return unless (defined($attr) && ($attr ne ""));
  68:     if (defined($self->{$attr}))
  69:       {
  70:         @{$self->{"_${attr}_save_"}} = @{$self->{$attr}}
  71:           unless $self->{"_${attr}_save_"};
  73:     $self->{$attr} = $val;
  74:     $self->{"_${attr}_modified_"} = 1;
  80:     if (($attr ne "dn") && !grep(/^$attr$/i,
@{$self->{"_oc_order_"}}))
  81:       {
  80:     if (($attr ne "dn") && !grep(/^$attr$/i,
@{$self->{"_oc_order_"}}))
  81:       {
 out
$=Mozilla::LDAP::Entry::STORE('Mozilla::LDAP::Entry=HASH(0x42d5dc)',
'description', 'ARRAY(0x49ec68)') from
/usr/local/lib/perl5/site_perl/Mozilla/LDAP/Entry.pm:364
 scalar context return from Mozilla::LDAP::Entry::STORE: ''
 in
$=Mozilla::LDAP::Entry::FETCH('Mozilla::LDAP::Entry=HASH(0x42d5dc)',
'description') from
/usr/local/lib/perl5/site_perl/Mozilla/LDAP/Entry.pm:364
  93:     my ($self, $attr) = ($_[$[], lc $_[$[ + 1]);
  95:     return unless defined($self->{$attr});
  96:     return if $self->{"_${attr}_deleted_"};
 out
$=Mozilla::LDAP::Entry::FETCH('Mozilla::LDAP::Entry=HASH(0x42d5dc)',
'description') from
/usr/local/lib/perl5/site_perl/Mozilla/LDAP/Entry.pm:364
 scalar context return from Mozilla::LDAP::Entry::FETCH: undef
Can't use an undefined value as an ARRAY reference at
/usr/local/lib/perl5/site_perl/Mozilla/LDAP/Entry.pm line 364, <IN>
chunk 37.

Mozilla::LDAP::Entry::addValue('Mozilla::LDAP::Entry=HASH(0x3e9cb0)',
'description', 'The Foo Company') called at ./foo.pl line 82

help.
Tom Spindler wrote:
>
> >doing:
> >       $entry->removeValue('description', 'Company of Foo' );
> >followed by:
> >       $entry->addValue('description', 'The Foo Company' );
> >results in:
> >
> >       Can't use an undefined value as an ARRAY reference at
> >       /usr/local/lib/perl5/site_perl/Mozilla/LDAP/Entry.pm line 364,
> >       <IN> chunk 7.
>
> If you only want to have one value, I suggest using
> $entry->setValue('foo', 'bar'). It seems to not be running into any
> autovivification issues.

The program used was a simple example I tossed together to demonstrate
the
problem.  The actual program I was trying to write is a bit more
complex.
I could do the data-munging outside the PerLDAP interface, and if this
doesn't get fixed soon, I probably will, but it seems to me that there's
no good reason not to expect this to work.

> (incidentally, was your program using 'use strict'?)

Yes.  Without 'use strict' you don't get the above error, but the value
added still doesn't end up in the database.
Without 'use strict', you don't get the error, but the added value
never gets into the database.  Note that the same thing happens when
a 'setValue()' follows a 'removeValue()'.

The following patch appears to fix the problem:

--- Entry.pm.bak        Thu Jan 21 15:52:42 1999
+++ Entry.pm    Fri Feb 12 09:47:08 1999
@@ -381,6 +381,10 @@
       $self->{"_oc_numattr_"}++;
     }

+  # If this attribute was set as 'deleted', it should no longer be
+  delete $self->{"_self_obj_"}->{"_${attr}_deleted_"}
+    if ( $self->{"_self_obj_"}->{"_${attr}_deleted_"} == 1 );
+
   return 1;
 }

@@ -416,6 +420,11 @@
   return 0 unless (defined($attr) && ($attr ne ""));

   $self->{$attr} = [@vals];
+
+  # If this attribute was set as 'deleted', it should no longer be
+  delete $self->{"_self_obj_"}->{"_${attr}_deleted_"}
+    if ( $self->{"_self_obj_"}->{"_${attr}_deleted_"} == 1 );
+
   return 1;
 }


bl
--
//====== Brett G. Lemoine -=- <bl@incyte.com> =======================\\
*** Bug 3137 has been marked as a duplicate of this bug. ***
Severity: normal → major
Well, even after applying the patch to fix the 'removeValue()',
'addValue()' problem, I'm seeing another problem.  This one,
at least, doesn't seem to be affecting the data.

I've tracked it down to being within the Mozilla::LDAP::Conn::update
routine -- specifcally, in the 'ldap_modify_s' call.

Anytime there is both an 'db' (remove) and an 'ab' (add) being done to
the same attribute of an entry, I get an error like:

        Bad free() ignored at (script name, line number).

That's about as deep as I can take this one -- any one else got any
ideas?

bl
--
//====== Brett G. Lemoine -=- <bl@incyte.com>
Status: ASSIGNED → RESOLVED
Closed: 21 years ago
Resolution: --- → FIXED
This is fixed, did a major update/rewrite on the code handling update() and
add(), particularly when tracking changes.
You need to log in before you can comment on or make changes to this bug.