[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Mon Oct 8 23:23:02 UTC 2018


The branch, master has been updated
       via  d25f88f pdb: Reduce code duplication in make_user_info()
       via  f613745 pdb: Fix some "(ret == true)" to just "(ret)"
       via  2329518 pdb: Use "sid_compose" where appropriate
       via  e7d3678 lib: Avoid the use of open_memstream in tevent_req_profile_string
       via  f36a538 tdb: Basic test for circular freelist fix
       via  bdacc41 tdb: Basic test for circular hash chain fix
       via  7e1ad4c tdb: Make the freelist walk circular-safe
       via  75e79ca tdb: Align integer types
       via  ade339c tdb: Make get_hash_length circular-safe
       via  e02c4a4 tdb: Make tdb_find_dead circular-safe
       via  6502f7a tdb: Make tdb_dump_chain circular-list safe
       via  e63f7bd tdb: Make tdb_find circular-safe
       via  b83763d tdb: Add tdb_chainwalk_check
       via  5ba7b20 registry: Don't use an uninitialized value
       via  f20d018 registry: Print failure of regdb_unpack_values
       via  a9ed0e9 registry: Add error checks to regdb_unpack_values
       via  2a35cbb registry: Add error checks to regdb_fetch_keys_internal
       via  1fb2d10 registry: Fix a typo
       via  ba787dc tdb_unpack: Protect against overflow
       via  0c0c79b tdb_unpack: Correct "len" arg for "B" format
       via  8f211ef tdb_unpack: Convert to size_t for internal calculations
      from  a5a4f97 gpo: Test process_group_policy in gp_sec_ext

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit d25f88f7baa4f463b73eac77ac96c2a724125e43
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Oct 5 14:49:17 2018 +0200

    pdb: Reduce code duplication in make_user_info()
    
    10 lines less and a few hundred (-O0) bytes .text less
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Tue Oct  9 01:22:53 CEST 2018 on sn-devel-144

commit f6137454b5aa0e3bac696723b785003ede19c9ef
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Oct 5 11:34:41 2018 +0200

    pdb: Fix some "(ret == true)" to just "(ret)"
    
    "ret" is a boolean, so this should not change semantics
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 2329518f32d3c772ddd8d6a27c62b18ff4de221a
Author: Volker Lendecke <vl at samba.org>
Date:   Fri Oct 5 12:12:39 2018 +0200

    pdb: Use "sid_compose" where appropriate
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit e7d3678ddb5916416193d553f3cc562627e7d8ab
Author: Volker Lendecke <vl at samba.org>
Date:   Sun Oct 7 14:47:26 2018 +0200

    lib: Avoid the use of open_memstream in tevent_req_profile_string
    
    Solaris does not have it.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=13629
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit f36a538cbd46e1652bfbd80862f2f03fa3e2f2d0
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 17:42:09 2018 +0200

    tdb: Basic test for circular freelist fix
    
    Try to store a record for which the (circular) freelist does not have
    any entry.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit bdacc41f4610478bb184815b89a26d875d075bf8
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 21:41:27 2018 +0200

    tdb: Basic test for circular hash chain fix
    
    This just walks tdb_find by searching for a nonexistent record
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 7e1ad4c58890fce29f9a03347b74b651b8b20305
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 17:12:42 2018 +0200

    tdb: Make the freelist walk circular-safe
    
    We can't really do the full check while the freelist is modified on the
    fly. As long as we don't merge any freelist entries, we should be good
    to apply this check.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 75e79ca54866ae41107607ebe4427a5bad2a499b
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 17:12:25 2018 +0200

    tdb: Align integer types
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit ade339c8c396dbeff44b24a3d0eb4e59f40ff25d
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 16:42:45 2018 +0200

    tdb: Make get_hash_length circular-safe
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit e02c4a417ed36373e0cbeb0d6c789444677b0c1e
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 15:25:59 2018 +0200

    tdb: Make tdb_find_dead circular-safe
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 6502f7a3d2ac384adf45b8bfbe47516cfa973c16
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 15:00:15 2018 +0200

    tdb: Make tdb_dump_chain circular-list safe
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit e63f7bd3a98023e2400ebb99a0f83098eb708eb5
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 15:21:01 2018 +0200

    tdb: Make tdb_find circular-safe
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit b83763d175057f3400c8ae2785efdab612a51b9a
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 15:20:10 2018 +0200

    tdb: Add tdb_chainwalk_check
    
    This captures the tdb_rescue protection against circular hash chains
    with a slow pointer updated only on every other record traverse
    
    If a hash chain has a loop, eventually the next_ptr
    will cycle around and be identical to the 'slow' pointer.
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 5ba7b2042b831931c9f88a5c740ad778a7e5f5e7
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 11:59:43 2018 +0200

    registry: Don't use an uninitialized value
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit f20d018aa9989f28a3f0ac53b6130c327b210224
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Oct 2 12:10:01 2018 +0200

    registry: Print failure of regdb_unpack_values
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit a9ed0e93bbd6cd32ed1d35b1279b401d1755d1e5
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Oct 2 13:16:23 2018 +0200

    registry: Add error checks to regdb_unpack_values
    
    This makes "regdb_unpack_values" take a size_t as buflen. The only
    caller calls it with TDB_DATA.dsize, which *is* size_t. Convert the
    internal "len" variable to the unsigned size_t as well and add overflow
    checks. This depends on tdb_unpack to either return -1 or a positive
    value less than or equal to the passed-in "size_t" buflen;
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 2a35cbb02f09e490f2b533849a08100881f12230
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Oct 2 13:16:04 2018 +0200

    registry: Add error checks to regdb_fetch_keys_internal
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 1fb2d10d381cf0dd8e66fc4867e936ef37011e64
Author: Volker Lendecke <vl at samba.org>
Date:   Tue Oct 2 12:00:30 2018 +0200

    registry: Fix a typo
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit ba787dc4ad3fd7195aee56567be9317358197bab
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 11:07:21 2018 +0200

    tdb_unpack: Protect against overflow
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 0c0c79b32e6c28f5e87caf57d9302c263952db71
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 11:05:46 2018 +0200

    tdb_unpack: Correct "len" arg for "B" format
    
    All but one of the users of the "B" format specifier passed in a pointer
    to uint32_t instead of what tdb_unpack expected, an "int". Because this
    is a purely internal API, change the tdb_unpack function and adjust that
    one caller.
    
    To reviewers: Please check carefully, thanks :-)
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 8f211efb3a79f24d9542e1c2472633cce2334208
Author: Volker Lendecke <vl at samba.org>
Date:   Thu Oct 4 10:57:47 2018 +0200

    tdb_unpack: Convert to size_t for internal calculations
    
    Signed-off-by: Volker Lendecke <vl at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 lib/tdb/common/dump.c                              |   9 +++
 lib/tdb/common/freelist.c                          |  17 ++++-
 lib/tdb/common/summary.c                           |   8 ++
 lib/tdb/common/tdb.c                               |  53 +++++++++++--
 lib/tdb/common/tdb_private.h                       |  10 +++
 lib/tdb/test/circular_chain.tdb                    | Bin 0 -> 272 bytes
 lib/tdb/test/circular_freelist.tdb                 | Bin 0 -> 400 bytes
 .../{run-zero-append.c => run-circular-chain.c}    |  29 +++----
 .../{run-zero-append.c => run-circular-freelist.c} |  35 +++++----
 lib/tdb/wscript                                    |   2 +
 lib/tevent/test_req.c                              |  15 +++-
 lib/util/tevent_req_profile.c                      |  85 +++++++++------------
 lib/util/tevent_req_profile.h                      |   8 +-
 source3/auth/token_util.c                          |   6 +-
 source3/auth/user_info.c                           |  42 ++++------
 source3/lib/util_tdb.c                             |  15 ++--
 source3/passdb/pdb_interface.c                     |   4 +-
 source3/printing/printing.c                        |   2 +-
 source3/registry/reg_backend_db.c                  |  66 ++++++++++++----
 source3/registry/reg_objects.c                     |   2 +-
 20 files changed, 265 insertions(+), 143 deletions(-)
 create mode 100644 lib/tdb/test/circular_chain.tdb
 create mode 100644 lib/tdb/test/circular_freelist.tdb
 copy lib/tdb/test/{run-zero-append.c => run-circular-chain.c} (52%)
 copy lib/tdb/test/{run-zero-append.c => run-circular-freelist.c} (52%)


Changeset truncated at 500 lines:

diff --git a/lib/tdb/common/dump.c b/lib/tdb/common/dump.c
index 73286b8..d4e3478 100644
--- a/lib/tdb/common/dump.c
+++ b/lib/tdb/common/dump.c
@@ -60,6 +60,7 @@ static tdb_off_t tdb_dump_record(struct tdb_context *tdb, int hash,
 
 static int tdb_dump_chain(struct tdb_context *tdb, int i)
 {
+	struct tdb_chainwalk_ctx chainwalk;
 	tdb_off_t rec_ptr, top;
 
 	if (i == -1) {
@@ -74,11 +75,19 @@ static int tdb_dump_chain(struct tdb_context *tdb, int i)
 	if (tdb_ofs_read(tdb, top, &rec_ptr) == -1)
 		return tdb_unlock(tdb, i, F_WRLCK);
 
+	tdb_chainwalk_init(&chainwalk, rec_ptr);
+
 	if (rec_ptr)
 		printf("hash=%d\n", i);
 
 	while (rec_ptr) {
+		bool ok;
 		rec_ptr = tdb_dump_record(tdb, i, rec_ptr);
+		ok = tdb_chainwalk_check(tdb, &chainwalk, rec_ptr);
+		if (!ok) {
+			printf("circular hash chain %d\n", i);
+			break;
+		}
 	}
 
 	return tdb_unlock(tdb, i, F_WRLCK);
diff --git a/lib/tdb/common/freelist.c b/lib/tdb/common/freelist.c
index 86fac2f..8870a41 100644
--- a/lib/tdb/common/freelist.c
+++ b/lib/tdb/common/freelist.c
@@ -444,6 +444,8 @@ static tdb_off_t tdb_allocate_from_freelist(
 	struct tdb_context *tdb, tdb_len_t length, struct tdb_record *rec)
 {
 	tdb_off_t rec_ptr, last_ptr, newrec_ptr;
+	struct tdb_chainwalk_ctx chainwalk;
+	bool modified;
 	struct {
 		tdb_off_t rec_ptr, last_ptr;
 		tdb_len_t rec_len;
@@ -466,6 +468,9 @@ static tdb_off_t tdb_allocate_from_freelist(
 	if (tdb_ofs_read(tdb, FREELIST_TOP, &rec_ptr) == -1)
 		return 0;
 
+	modified = false;
+	tdb_chainwalk_init(&chainwalk, rec_ptr);
+
 	bestfit.rec_ptr = 0;
 	bestfit.last_ptr = 0;
 	bestfit.rec_len = 0;
@@ -526,6 +531,8 @@ static tdb_off_t tdb_allocate_from_freelist(
 				merge_created_candidate = true;
 			}
 
+			modified = true;
+
 			continue;
 		}
 
@@ -542,6 +549,14 @@ static tdb_off_t tdb_allocate_from_freelist(
 		last_ptr = rec_ptr;
 		rec_ptr = rec->next;
 
+		if (!modified) {
+			bool ok;
+			ok = tdb_chainwalk_check(tdb, &chainwalk, rec_ptr);
+			if (!ok) {
+				return 0;
+			}
+		}
+
 		/* if we've found a record that is big enough, then
 		   stop searching if its also not too big. The
 		   definition of 'too big' changes as we scan
@@ -605,7 +620,7 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, int hash, tdb_len_t length,
 		       struct tdb_record *rec)
 {
 	tdb_off_t ret;
-	int i;
+	uint32_t i;
 
 	if (tdb->max_dead_records == 0) {
 		/*
diff --git a/lib/tdb/common/summary.c b/lib/tdb/common/summary.c
index c9b5bc4..a93eb93 100644
--- a/lib/tdb/common/summary.c
+++ b/lib/tdb/common/summary.c
@@ -72,18 +72,26 @@ static size_t tally_mean(const struct tally *tally)
 static size_t get_hash_length(struct tdb_context *tdb, unsigned int i)
 {
 	tdb_off_t rec_ptr;
+	struct tdb_chainwalk_ctx chainwalk;
 	size_t count = 0;
 
 	if (tdb_ofs_read(tdb, TDB_HASH_TOP(i), &rec_ptr) == -1)
 		return 0;
 
+	tdb_chainwalk_init(&chainwalk, rec_ptr);
+
 	/* keep looking until we find the right record */
 	while (rec_ptr) {
 		struct tdb_record r;
+		bool ok;
 		++count;
 		if (tdb_rec_read(tdb, rec_ptr, &r) == -1)
 			return 0;
 		rec_ptr = r.next;
+		ok = tdb_chainwalk_check(tdb, &chainwalk, rec_ptr);
+		if (!ok) {
+			return SIZE_MAX;
+		}
 	}
 	return count;
 }
diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c
index 04f7f97..4e433c8 100644
--- a/lib/tdb/common/tdb.c
+++ b/lib/tdb/common/tdb.c
@@ -79,19 +79,53 @@ static int tdb_key_compare(TDB_DATA key, TDB_DATA data, void *private_data)
 	return memcmp(data.dptr, key.dptr, data.dsize);
 }
 
+void tdb_chainwalk_init(struct tdb_chainwalk_ctx *ctx, tdb_off_t ptr)
+{
+	*ctx = (struct tdb_chainwalk_ctx) { .slow_ptr = ptr };
+}
+
+bool tdb_chainwalk_check(struct tdb_context *tdb,
+			 struct tdb_chainwalk_ctx *ctx,
+			 tdb_off_t next_ptr)
+{
+	int ret;
+
+	if (ctx->slow_chase) {
+		ret = tdb_ofs_read(tdb, ctx->slow_ptr, &ctx->slow_ptr);
+		if (ret == -1) {
+			return false;
+		}
+	}
+	ctx->slow_chase = !ctx->slow_chase;
+
+	if (next_ptr == ctx->slow_ptr) {
+		tdb->ecode = TDB_ERR_CORRUPT;
+		TDB_LOG((tdb, TDB_DEBUG_ERROR,
+			 "tdb_chainwalk_check: circular chain\n"));
+		return false;
+	}
+
+	return true;
+}
+
 /* Returns 0 on fail.  On success, return offset of record, and fills
    in rec */
 static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, uint32_t hash,
 			struct tdb_record *r)
 {
 	tdb_off_t rec_ptr;
+	struct tdb_chainwalk_ctx chainwalk;
 
 	/* read in the hash top */
 	if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
 		return 0;
 
+	tdb_chainwalk_init(&chainwalk, rec_ptr);
+
 	/* keep looking until we find the right record */
 	while (rec_ptr) {
+		bool ok;
+
 		if (tdb_rec_read(tdb, rec_ptr, r) == -1)
 			return 0;
 
@@ -102,13 +136,12 @@ static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, uint32_t hash,
 				      NULL) == 0) {
 			return rec_ptr;
 		}
-		/* detect tight infinite loop */
-		if (rec_ptr == r->next) {
-			tdb->ecode = TDB_ERR_CORRUPT;
-			TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_find: loop detected.\n"));
+		rec_ptr = r->next;
+
+		ok = tdb_chainwalk_check(tdb, &chainwalk, rec_ptr);
+		if (!ok) {
 			return 0;
 		}
-		rec_ptr = r->next;
 	}
 	tdb->ecode = TDB_ERR_NOEXIST;
 	return 0;
@@ -490,6 +523,7 @@ tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
 			tdb_off_t *p_last_ptr)
 {
 	tdb_off_t rec_ptr, last_ptr;
+	struct tdb_chainwalk_ctx chainwalk;
 	tdb_off_t best_rec_ptr = 0;
 	tdb_off_t best_last_ptr = 0;
 	struct tdb_record best = { .rec_len = UINT32_MAX };
@@ -502,8 +536,12 @@ tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
 	if (tdb_ofs_read(tdb, last_ptr, &rec_ptr) == -1)
 		return 0;
 
+	tdb_chainwalk_init(&chainwalk, rec_ptr);
+
 	/* keep looking until we find the right record */
 	while (rec_ptr) {
+		bool ok;
+
 		if (tdb_rec_read(tdb, rec_ptr, r) == -1)
 			return 0;
 
@@ -515,6 +553,11 @@ tdb_off_t tdb_find_dead(struct tdb_context *tdb, uint32_t hash,
 		}
 		last_ptr = rec_ptr;
 		rec_ptr = r->next;
+
+		ok = tdb_chainwalk_check(tdb, &chainwalk, rec_ptr);
+		if (!ok) {
+			return 0;
+		}
 	}
 
 	if (best.rec_len == UINT32_MAX) {
diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h
index eeac10a..307cad9 100644
--- a/lib/tdb/common/tdb_private.h
+++ b/lib/tdb/common/tdb_private.h
@@ -191,6 +191,11 @@ struct tdb_lock_type {
 	uint32_t ltype;
 };
 
+struct tdb_chainwalk_ctx {
+	tdb_off_t slow_ptr;
+	bool slow_chase;
+};
+
 struct tdb_traverse_lock {
 	struct tdb_traverse_lock *next;
 	uint32_t off;
@@ -198,6 +203,11 @@ struct tdb_traverse_lock {
 	int lock_rw;
 };
 
+void tdb_chainwalk_init(struct tdb_chainwalk_ctx *ctx, tdb_off_t ptr);
+bool tdb_chainwalk_check(struct tdb_context *tdb,
+			 struct tdb_chainwalk_ctx *ctx,
+			 tdb_off_t next_ptr);
+
 enum tdb_lock_flags {
 	/* WAIT == F_SETLKW, NOWAIT == F_SETLK */
 	TDB_LOCK_NOWAIT = 0,
diff --git a/lib/tdb/test/circular_chain.tdb b/lib/tdb/test/circular_chain.tdb
new file mode 100644
index 0000000..1e143d3
Binary files /dev/null and b/lib/tdb/test/circular_chain.tdb differ
diff --git a/lib/tdb/test/circular_freelist.tdb b/lib/tdb/test/circular_freelist.tdb
new file mode 100644
index 0000000..f1c85e5
Binary files /dev/null and b/lib/tdb/test/circular_freelist.tdb differ
diff --git a/lib/tdb/test/run-zero-append.c b/lib/tdb/test/run-circular-chain.c
similarity index 52%
copy from lib/tdb/test/run-zero-append.c
copy to lib/tdb/test/run-circular-chain.c
index f9eba1b..4fb32a2 100644
--- a/lib/tdb/test/run-zero-append.c
+++ b/lib/tdb/test/run-circular-chain.c
@@ -17,25 +17,26 @@
 int main(int argc, char *argv[])
 {
 	struct tdb_context *tdb;
-	TDB_DATA key, data;
+	TDB_DATA key;
+
+	plan_tests(3);
+	tdb = tdb_open_ex(
+		"test/circular_chain.tdb",
+		0,
+		TDB_DEFAULT,
+		O_RDONLY,
+		0600,
+		&taplogctx,
+		NULL);
 
-	plan_tests(4);
-	tdb = tdb_open_ex(NULL, 1024, TDB_INTERNAL, O_CREAT|O_TRUNC|O_RDWR,
-			  0600, &taplogctx, NULL);
 	ok1(tdb);
+	key.dsize = strlen("x");
+	key.dptr = discard_const_p(uint8_t, "x");
 
-	/* Tickle bug on appending zero length buffer to zero length buffer. */
-	key.dsize = strlen("hi");
-	key.dptr = discard_const_p(uint8_t, "hi");
-	data.dptr = discard_const_p(uint8_t, "world");
-	data.dsize = 0;
+	ok1(tdb_exists(tdb, key) == 0);
+	ok1(tdb_error(tdb) == TDB_ERR_CORRUPT);
 
-	ok1(tdb_append(tdb, key, data) == 0);
-	ok1(tdb_append(tdb, key, data) == 0);
-	data = tdb_fetch(tdb, key);
-	ok1(data.dsize == 0);
 	tdb_close(tdb);
-	free(data.dptr);
 
 	return exit_status();
 }
diff --git a/lib/tdb/test/run-zero-append.c b/lib/tdb/test/run-circular-freelist.c
similarity index 52%
copy from lib/tdb/test/run-zero-append.c
copy to lib/tdb/test/run-circular-freelist.c
index f9eba1b..f1bec87 100644
--- a/lib/tdb/test/run-zero-append.c
+++ b/lib/tdb/test/run-circular-freelist.c
@@ -19,23 +19,32 @@ int main(int argc, char *argv[])
 	struct tdb_context *tdb;
 	TDB_DATA key, data;
 
-	plan_tests(4);
-	tdb = tdb_open_ex(NULL, 1024, TDB_INTERNAL, O_CREAT|O_TRUNC|O_RDWR,
-			  0600, &taplogctx, NULL);
+	plan_tests(3);
+	tdb = tdb_open_ex(
+		"test/circular_freelist.tdb",
+		0,
+		TDB_DEFAULT,
+		O_RDWR,
+		0600,
+		&taplogctx,
+		NULL);
+
 	ok1(tdb);
 
-	/* Tickle bug on appending zero length buffer to zero length buffer. */
-	key.dsize = strlen("hi");
-	key.dptr = discard_const_p(uint8_t, "hi");
-	data.dptr = discard_const_p(uint8_t, "world");
-	data.dsize = 0;
+	/*
+	 * All freelist records are just 1 byte key and value. Insert
+	 * something that will walk the whole freelist and hit the
+	 * circle.
+	 */
+	key.dsize = strlen("x");
+	key.dptr = discard_const_p(uint8_t, "x");
+	data.dsize = strlen("too long");
+	data.dptr = discard_const_p(uint8_t, "too long");
+
+	ok1(tdb_store(tdb, key, data, TDB_INSERT) == -1);
+	ok1(tdb_error(tdb) == TDB_ERR_CORRUPT);
 
-	ok1(tdb_append(tdb, key, data) == 0);
-	ok1(tdb_append(tdb, key, data) == 0);
-	data = tdb_fetch(tdb, key);
-	ok1(data.dsize == 0);
 	tdb_close(tdb);
-	free(data.dptr);
 
 	return exit_status();
 }
diff --git a/lib/tdb/wscript b/lib/tdb/wscript
index 6ffca9e..3ab21fc 100644
--- a/lib/tdb/wscript
+++ b/lib/tdb/wscript
@@ -55,6 +55,8 @@ tdb1_unit_tests = [
     'run-mutex-transaction1',
     'run-mutex-die',
     'run-mutex1',
+    'run-circular-chain',
+    'run-circular-freelist',
 ]
 
 def options(opt):
diff --git a/lib/tevent/test_req.c b/lib/tevent/test_req.c
index 565ef31..2274a8c 100644
--- a/lib/tevent/test_req.c
+++ b/lib/tevent/test_req.c
@@ -170,6 +170,7 @@ static bool test_tevent_req_profile2(struct torture_context *tctx,
 	pid_t pid1, pid2;
 	enum tevent_req_state state1, state2;
 	uint64_t err1, err2;
+	char *printstring;
 	ssize_t pack_len;
 	int err;
 	bool ok;
@@ -189,7 +190,12 @@ static bool test_tevent_req_profile2(struct torture_context *tctx,
 	TALLOC_FREE(req);
 	TALLOC_FREE(ev);
 
-	tevent_req_profile_print(p1, stdout, 0, UINT_MAX);
+	printstring = tevent_req_profile_string(tctx, p1, 0, UINT_MAX);
+	torture_assert_not_null(
+		tctx,
+		printstring,
+		"tevent_req_profile_string failed\n");
+	printf("%s\n", printstring);
 
 	pack_len = tevent_req_profile_pack(p1, NULL, 0);
 	torture_assert(tctx, pack_len>0, "profile_pack failed\n");
@@ -212,7 +218,12 @@ static bool test_tevent_req_profile2(struct torture_context *tctx,
 					 "profile_unpack failed\n");
 	}
 
-	tevent_req_profile_print(p2, stdout, 0, UINT_MAX);
+	printstring = tevent_req_profile_string(tctx, p2, 0, UINT_MAX);
+	torture_assert_not_null(
+		tctx,
+		printstring,
+		"tevent_req_profile_string failed\n");
+	printf("%s\n", printstring);
 
 	tevent_req_profile_get_name(p1, &str1);
 	tevent_req_profile_get_name(p2, &str2);
diff --git a/lib/util/tevent_req_profile.c b/lib/util/tevent_req_profile.c
index 522741c..2d280f7 100644
--- a/lib/util/tevent_req_profile.c
+++ b/lib/util/tevent_req_profile.c
@@ -29,10 +29,11 @@
 #include "lib/util/time_basic.h"
 #include "lib/util/memory.h"
 
-int tevent_req_profile_print(const struct tevent_req_profile *profile,
-			     FILE *fp,
-			     unsigned indent,
-			     unsigned max_indent)
+static bool tevent_req_profile_string_internal(
+	const struct tevent_req_profile *profile,
+	unsigned indent,
+	unsigned max_indent,
+	char **string)
 {
 	struct timeval start, stop, diff;
 	struct timeval_buf start_buf, stop_buf;
@@ -44,7 +45,7 @@ int tevent_req_profile_print(const struct tevent_req_profile *profile,
 	const char *state_buf = NULL;
 	uint64_t user_error;
 	const struct tevent_req_profile *sub = NULL;
-	int ret;
+	char *result;
 
 	tevent_req_profile_get_name(profile, &req_name);
 
@@ -85,8 +86,8 @@ int tevent_req_profile_print(const struct tevent_req_profile *profile,
 		break;
 	}
 
-	ret = fprintf(
-		fp,
+	result = talloc_asprintf_append_buffer(
+		*string,
 		"%*s[%s] %s [%s] %s [%s] [%ju.%.6ju] -> %s (%d %"PRIu64"))\n",
 		indent,
 		"",
@@ -100,72 +101,58 @@ int tevent_req_profile_print(const struct tevent_req_profile *profile,
 		state_buf,
 		(int)state,
 		user_error);
-
-	if (ret < 0) {
-		return ret;
+	if (result == NULL) {
+		return false;
 	}
+	*string = result;
 
 	indent += 1;
 
 	if (indent >= max_indent) {
-		return ret;
+		return true;
 	}
 
 	for (sub = tevent_req_profile_get_subprofiles(profile);
 	     sub != NULL;
 	     sub = tevent_req_profile_next(sub)) {
-		int subret;
-
-		subret = tevent_req_profile_print(sub, fp, indent, max_indent);
-		if (subret < 0) {
-			return subret;
-		}
-
-		ret += subret;
-
-		if (ret < subret) {
-			/* overflow */
-			return -1;
+		bool ret;
+
+		ret = tevent_req_profile_string_internal(
+			sub,
+			indent,
+			max_indent,
+			string);
+		if (!ret) {


-- 
Samba Shared Repository



More information about the samba-cvs mailing list