Blame SOURCES/0037-Issue-4595-Paged-search-lookthroughlimit-bug-4602.patch

b03d2c
From 0bdb7445af5be162e18c26f7fc2b75536c467748 Mon Sep 17 00:00:00 2001
b03d2c
From: James Chapman <jachapma@redhat.com>
b03d2c
Date: Fri, 19 Feb 2021 16:32:22 +0000
b03d2c
Subject: [PATCH 4/4] Issue 4595 - Paged search lookthroughlimit bug (#4602)
b03d2c
b03d2c
Bug Description: During a paged search with lookthroughlimit enabled,
b03d2c
lookthroughcount is used to keep track of how many entries are
b03d2c
examined. A paged search reads ahead one entry to catch the end of the
b03d2c
search so it doesn't show the prompt when there are no more entries.
b03d2c
lookthroughcount doesn't take read ahead into account when tracking
b03d2c
how many entries have been examined.
b03d2c
b03d2c
Fix Description: Keep lookthroughcount in sync with read ahead by
b03d2c
by decrementing it during read ahead roll back.
b03d2c
b03d2c
Fixes: https://github.com/389ds/389-ds-base/issues/4595
b03d2c
b03d2c
Relates: https://github.com/389ds/389-ds-base/issues/4513
b03d2c
b03d2c
Reviewed by: droideck, mreynolds389, Firstyear, progier389 (Many thanks)
b03d2c
---
b03d2c
 dirsrvtests/tests/suites/basic/basic_test.py | 85 ++++++++++++++++++++
b03d2c
 ldap/servers/slapd/back-ldbm/ldbm_search.c   |  1 +
b03d2c
 2 files changed, 86 insertions(+)
b03d2c
b03d2c
diff --git a/dirsrvtests/tests/suites/basic/basic_test.py b/dirsrvtests/tests/suites/basic/basic_test.py
b03d2c
index 332f5bb8d..e1a31175a 100644
b03d2c
--- a/dirsrvtests/tests/suites/basic/basic_test.py
b03d2c
+++ b/dirsrvtests/tests/suites/basic/basic_test.py
b03d2c
@@ -95,6 +95,24 @@ def rootdse_attr(topology_st, request):
b03d2c
     return rootdse_attr_name
b03d2c
 
b03d2c
 
b03d2c
+def change_conf_attr(topology_st, suffix, attr_name, attr_value):
b03d2c
+    """Change configuration attribute in the given suffix.
b03d2c
+
b03d2c
+    Returns previous attribute value.
b03d2c
+    """
b03d2c
+
b03d2c
+    entry = DSLdapObject(topology_st.standalone, suffix)
b03d2c
+
b03d2c
+    attr_value_bck = entry.get_attr_val_bytes(attr_name)
b03d2c
+    log.info('Set %s to %s. Previous value - %s. Modified suffix - %s.' % (
b03d2c
+        attr_name, attr_value, attr_value_bck, suffix))
b03d2c
+    if attr_value is None:
b03d2c
+        entry.remove_all(attr_name)
b03d2c
+    else:
b03d2c
+        entry.replace(attr_name, attr_value)
b03d2c
+    return attr_value_bck
b03d2c
+
b03d2c
+
b03d2c
 def test_basic_ops(topology_st, import_example_ldif):
b03d2c
     """Tests adds, mods, modrdns, and deletes operations
b03d2c
 
b03d2c
@@ -607,6 +625,73 @@ def test_basic_searches(topology_st, import_example_ldif):
b03d2c
     log.info('test_basic_searches: PASSED')
b03d2c
 
b03d2c
 
b03d2c
+@pytest.mark.parametrize('limit,resp',
b03d2c
+                         ((('200'), 'PASS'),
b03d2c
+                         (('50'), ldap.ADMINLIMIT_EXCEEDED)))
b03d2c
+def test_basic_search_lookthroughlimit(topology_st, limit, resp, import_example_ldif):
b03d2c
+    """
b03d2c
+    Tests normal search with lookthroughlimit set high and low.
b03d2c
+
b03d2c
+    :id: b5119970-6c9f-41b7-9649-de9233226fec
b03d2c
+
b03d2c
+    :setup: Standalone instance, add example.ldif to the database, search filter (uid=*).
b03d2c
+
b03d2c
+    :steps:
b03d2c
+         1. Import ldif user file.
b03d2c
+         2. Change lookthroughlimit to 200.
b03d2c
+         3. Bind to server as low priv user
b03d2c
+         4. Run search 1 with "high" lookthroughlimit.
b03d2c
+         5. Change lookthroughlimit to 50.
b03d2c
+         6. Run search 2 with "low" lookthroughlimit.
b03d2c
+         8. Delete user from DB.
b03d2c
+         9. Reset lookthroughlimit to original.
b03d2c
+
b03d2c
+    :expectedresults:
b03d2c
+         1. First search should complete with no error.
b03d2c
+         2. Second search should return ldap.ADMINLIMIT_EXCEEDED error.
b03d2c
+    """
b03d2c
+
b03d2c
+    log.info('Running test_basic_search_lookthroughlimit...')
b03d2c
+
b03d2c
+    search_filter = "(uid=*)"
b03d2c
+
b03d2c
+    ltl_orig = change_conf_attr(topology_st, 'cn=config,cn=ldbm database,cn=plugins,cn=config', 'nsslapd-lookthroughlimit', limit)
b03d2c
+
b03d2c
+    try:
b03d2c
+        users = UserAccounts(topology_st.standalone, DEFAULT_SUFFIX, rdn=None)
b03d2c
+        user = users.create_test_user()
b03d2c
+        user.replace('userPassword', PASSWORD)
b03d2c
+    except ldap.LDAPError as e:
b03d2c
+        log.fatal('Failed to create test user: error ' + e.args[0]['desc'])
b03d2c
+        assert False
b03d2c
+
b03d2c
+    try:
b03d2c
+        conn = UserAccount(topology_st.standalone, user.dn).bind(PASSWORD)
b03d2c
+    except ldap.LDAPError as e:
b03d2c
+        log.fatal('Failed to bind test user: error ' + e.args[0]['desc'])
b03d2c
+        assert False
b03d2c
+
b03d2c
+    try:
b03d2c
+        if resp == ldap.ADMINLIMIT_EXCEEDED:
b03d2c
+            with pytest.raises(ldap.ADMINLIMIT_EXCEEDED):
b03d2c
+                searchid = conn.search(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, search_filter)
b03d2c
+                rtype, rdata = conn.result(searchid)
b03d2c
+        else:
b03d2c
+            searchid = conn.search(DEFAULT_SUFFIX, ldap.SCOPE_SUBTREE, search_filter)
b03d2c
+            rtype, rdata = conn.result(searchid)
b03d2c
+            assert(len(rdata) == 151) #151 entries in the imported ldif file using "(uid=*)"
b03d2c
+    except ldap.LDAPError as e:
b03d2c
+        log.fatal('Failed to perform search: error ' + e.args[0]['desc'])
b03d2c
+        assert False
b03d2c
+
b03d2c
+    finally:
b03d2c
+        #Cleanup
b03d2c
+        change_conf_attr(topology_st, 'cn=config,cn=ldbm database,cn=plugins,cn=config', 'nsslapd-lookthroughlimit', ltl_orig)
b03d2c
+        user.delete()
b03d2c
+
b03d2c
+    log.info('test_basic_search_lookthroughlimit: PASSED')
b03d2c
+
b03d2c
+
b03d2c
 @pytest.fixture(scope="module")
b03d2c
 def add_test_entry(topology_st, request):
b03d2c
     # Add test entry
b03d2c
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c
b03d2c
index 6e22debde..d0f52b6f7 100644
b03d2c
--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c
b03d2c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c
b03d2c
@@ -1885,6 +1885,7 @@ ldbm_back_prev_search_results(Slapi_PBlock *pb)
b03d2c
             sr->sr_entry = NULL;
b03d2c
         }
b03d2c
         idl_iterator_decrement(&(sr->sr_current));
b03d2c
+        --sr->sr_lookthroughcount;
b03d2c
     }
b03d2c
     return;
b03d2c
 }
b03d2c
-- 
b03d2c
2.31.1
b03d2c