> >>>> Looking at the code in sssvlv.c, it uses tavl_find3() to search the
> >>>> values, but the
> >>>> code in tavl_find3() looks to me that it only works properly with an
> >>>> exact match
> >>>> type of matching rule:
> >>>>
> >>>> Avlnode *
> >>>> tavl_find3( Avlnode *root, const void *data, AVL_CMP fcmp, int *ret )
> >>>> {
> >>>> int cmp = -1, dir;
> >>>> Avlnode *prev = root;
> >>>>
> >>>> while ( root != 0&& (cmp = (*fcmp)( data, root->avl_data )) != 0 ) {
> >>>> prev = root;
> >>>> dir = cmp> 0;
> >>>> root = avl_child( root, dir );
> >>>> }
> >>>> *ret = cmp;
> >>>> return root ? root : prev;
> >>>> }
> >>>>
> >>>> since the while loop terminates when the fcmp function returns 0 (i.e.
> >>>> exact match).
> >>>>
> >>>
> >>> I think I've worked out where the problem is.
> >>> Firstly, there's a comment before tavl_find3() saying
> >>> /*
> >>> * tavl_find2 - returns Avlnode instead of data pointer.
> >>> * tavl_find3 - as above, but returns Avlnode even if no match is found.
> >>> * also set *ret = last comparison result, or -1 if root == NULL.
> >>> */
> >>>
> >>> but the "or -1 if root == NULL" is not done.
>
> Not true; since cmp is initialized to -1, it will return -1 when the function
> is entered with root == NULL. There is no bug in this part.It depends how you
> read the comment. If the function is *entered* with root == NULL, then I
> agree that -1 is returned, but if the while loop exits with root == NULL then
> the last comparison result is returned, which causes problems to the call in
> sssvlv.c.>
> >>> Secondly, if no exact match is found, prev is returned which may point to
> >>> a node which is less than the search
> >>> node, depending on what the tree looks like, but we really want a pointer
> >>> to the last node which was greater than
> >>> the search node to be returned.
> >>>
> >>> Once these fixes are done, the correct node is returned by tavl_find3 to
> >>> the call in send_list() in sssvlv.c (line 523).
>
> This fix is also not correct. Possibly tavl_find3() has been misused in the
> sssvlv code, but this function works as designed.
>Possibly. But with the patch as suggested, the sssvlv code works correctly and
>gets the correct node.If you think these changes might break other uses of
>tavl_find3() (of which there didn't seem to be many), perhapstavl_find4()
>could be added.
> >>> There is another bug in send_list() in sssvlv.c, at lines 535-544:
> >>>
> >>> if ( i> 0 ) {
> >>> tmp_node = tavl_end(so->so_tree, TAVL_DIR_RIGHT);
> >>> dir = TAVL_DIR_LEFT;
> >>> } else {
> >>> tmp_node = tavl_end(so->so_tree, TAVL_DIR_LEFT);
> >>> dir = TAVL_DIR_RIGHT;
> >>> }
> >>> for (i=0; tmp_node != cur_node;
> >>> tmp_node = tavl_next( tmp_node, dir ), i++);
> >>> so->so_vlv_target = i;
> >>> This code is ok if the cur_node is in the left hand side of the tree, but
> >>> if it is in the rhs of the tree so_vlv_target is set
> >>> to an offset from the end of the list, rather than the beginning.
>
> OK, looks like you have a good patch for this.
>
> >> One more issue: the most recent draft spec for vlv
> >> (http://tools.ietf.org/html/draft-ietf-ldapext-ldapv3-vlv-09) states that
> >> the offset field in the vlv request has range 1..maxInt whereas the
> >> targetPosition in the vlv response has range 0..maxInt.
> >>
> >> However, my interpretation of the spec is that offset and targetPosition
> >> represent the same thing, i.e. the position of the target entry in the
> >> list, with the first entry having offset/targetPosition = 1.
> >>
> >> If that interpretation is correct, the assignment of so_vlv_target in the
> >> code above is off by one, since i will be zero if cur_node is at the
> >> beginning of the list.
> >>
> >
> > I've uploaded a patch to ftp.openldap.org,
> > incoming/Chris-Card-110708.ITS-6985-fix.patch