dirsrvtests/tests/tickets/ticket49104_test.py | 80 ++++++++++++++++++++++++++
ldap/servers/slapd/tools/dbscan.c | 17 +++++
2 files changed, 96 insertions(+), 1 deletion(-)
New commits:
commit c5a67ce1ad297cf59b5dd0e47c9896e261aba08c
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Jan 27 15:41:08 2017 -0800
Ticket #49104 - Add CI test
Description: dbscan-bin crashing due to a segmentation fault
diff --git a/dirsrvtests/tests/tickets/ticket49104_test.py
b/dirsrvtests/tests/tickets/ticket49104_test.py
new file mode 100644
index 0000000..9840b1d
--- /dev/null
+++ b/dirsrvtests/tests/tickets/ticket49104_test.py
@@ -0,0 +1,80 @@
+# --- BEGIN COPYRIGHT BLOCK ---
+# Copyright (C) 2017 Red Hat, Inc.
+# All rights reserved.
+#
+# License: GPL (version 3 or any later version).
+# See LICENSE for details.
+# --- END COPYRIGHT BLOCK ---
+#
+import logging
+import subprocess
+
+import pytest
+from lib389.tasks import *
+from lib389.topologies import topology_st
+
+log = logging.getLogger(__name__)
+
+def test_ticket49104_setup(topology_st):
+ """
+ Generate an ldif file having 10K entries and import it.
+ """
+ # Generate a test ldif (100k entries)
+ ldif_dir = topology_st.standalone.get_ldif_dir()
+ import_ldif = ldif_dir + '/49104.ldif'
+ try:
+ topology_st.standalone.buildLDIF(100000, import_ldif)
+ except OSError as e:
+ log.fatal('ticket 49104: failed to create test ldif,\
+ error: %s - %s' % (e.errno, e.strerror))
+ assert False
+
+ # Online
+ try:
+ topology_st.standalone.tasks.importLDIF(suffix=DEFAULT_SUFFIX,
+ input_file=import_ldif,
+ args={TASK_WAIT: True})
+ except ValueError:
+ log.fatal('ticket 49104: Online import failed')
+ assert False
+
+def test_ticket49104(topology_st):
+ """
+ Run dbscan with valgrind changing the truncate size.
+ If there is no Invalid report, we can claim the test has passed.
+ """
+ log.info("Test ticket 49104 -- dbscan crashes by memory corruption")
+ myvallog = '/tmp/val49104.out'
+ if os.path.exists(myvallog):
+ os.remove(myvallog)
+ prog = os.path.join(topology_st.standalone.get_bin_dir(), 'dbscan-bin')
+ valcmd = 'valgrind --tool=memcheck --leak-check=yes --num-callers=40
--log-file=%s ' % myvallog
+ id2entry = os.path.join(topology_st.standalone.dbdir, DEFAULT_BENAME,
'id2entry.db')
+
+ for i in range(20, 30):
+ cmd = valcmd + '%s -f %s -t %d -R' % (prog, id2entry , i)
+ log.info('Running script: %s' % cmd)
+ proc = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
+ outs = ''
+ try:
+ outs = proc.communicate()
+ except OSError as e:
+ log.exception('dbscan: error executing (%s): error %d - %s' %
+ (cmd, e.errno, e.strerror))
+ raise e
+
+ grep = 'egrep "Invalid read|Invalid write" %s' % myvallog
+ p = os.popen(grep, "r")
+ l = p.readline()
+ if 'Invalid' in l:
+ log.fatal('ERROR: valgrind reported invalid read/write: %s' % l)
+ assert False
+
+ log.info('ticket 49104 - PASSED')
+
+
+if __name__ == '__main__':
+ # Run isolated
+ # -s for DEBUG mode
+ CURRENT_FILE = os.path.realpath(__file__)
+ pytest.main("-s %s" % CURRENT_FILE)
commit efeb2f6e873df32ce7545fa1fb319806d2108fda
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Thu Jan 26 15:10:46 2017 -0800
Ticket #49104 - dbscan-bin crashing due to a segmentation fault
Description: There was a logic error in format_raw. When a truncate
option (-t width) is given, the function cut the output and replace
the last 5 bytes with " ...\0". The position to start the replace
was not correct in some case.
https://fedorahosted.org/389/ticket/49104
Reviewed by wibrown(a)redhat.com (Thank you, William!!)
diff --git a/ldap/servers/slapd/tools/dbscan.c b/ldap/servers/slapd/tools/dbscan.c
index 0a7f85e..33252b8 100644
--- a/ldap/servers/slapd/tools/dbscan.c
+++ b/ldap/servers/slapd/tools/dbscan.c
@@ -202,6 +202,7 @@ static char *format_raw(unsigned char *s, int len, int flags,
return NULL;
for (p = s, o = buf, i = 0; i < len && o < bufend; p++, i++) {
+ int ishex = 0;
if ((*p == '%') || (*p <= ' ') || (*p >= 126)) {
/* index keys are stored with their trailing NUL */
if ((*p == 0) && (i == len-1))
@@ -215,18 +216,32 @@ static char *format_raw(unsigned char *s, int len, int flags,
*o++ = '%';
*o++ = hex[*p / 16];
*o++ = hex[*p % 16];
+ ishex = 1;
}
} else {
*o++ = *p;
}
if (truncatesiz > 0 && o > bufend - 5) {
/* truncate it */
+ /*
+ * Padding " ...\0" at the end of the buf.
+ * If dumped as %##, truncate the partial value if any.
+ */
+ o = bufend - 5;
+ if (ishex) {
+ if ((o > buf) && *(o-1) == '%') {
+ o -= 1;
+ } else if ((o > buf + 1) && *(o-2) == '%') {
+ o -= 2;
+ }
+ }
strcpy((char *)o, " ...");
i = len;
o += 4;
+ break;
}
}
- *o = 0;
+ *o = '\0';
return (char *)buf;
}