realloc() has that horrible overloaded free semantic when size is 0:
[samba.git] / lib / tdb / common / tdb.c
index 8c61ec1a89d0e6303a507e24455940d9eeff13ab..b78f74cc693e9f4fd3b26ba2e06b078f31bb0965 100644 (file)
@@ -96,6 +96,11 @@ static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, uint32_t hash,
                                      NULL) == 0) {
                        return rec_ptr;
                }
                                      NULL) == 0) {
                        return rec_ptr;
                }
+               /* detect tight infinite loop */
+               if (rec_ptr == r->next) {
+                       TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_find: loop detected.\n"));
+                       return TDB_ERRCODE(TDB_ERR_CORRUPT, 0);
+               }
                rec_ptr = r->next;
        }
        return TDB_ERRCODE(TDB_ERR_NOEXIST, 0);
                rec_ptr = r->next;
        }
        return TDB_ERRCODE(TDB_ERR_NOEXIST, 0);
@@ -579,8 +584,13 @@ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
        if (dbuf.dptr == NULL) {
                dbuf.dptr = (unsigned char *)malloc(new_dbuf.dsize);
        } else {
        if (dbuf.dptr == NULL) {
                dbuf.dptr = (unsigned char *)malloc(new_dbuf.dsize);
        } else {
-               unsigned char *new_dptr = (unsigned char *)realloc(dbuf.dptr,
-                                                    dbuf.dsize + new_dbuf.dsize);
+               unsigned int new_len = dbuf.dsize + new_dbuf.dsize;
+               unsigned char *new_dptr;
+
+               /* realloc '0' is special: don't do that. */
+               if (new_len == 0)
+                       new_len = 1;
+               new_dptr = (unsigned char *)realloc(dbuf.dptr, new_len);
                if (new_dptr == NULL) {
                        free(dbuf.dptr);
                }
                if (new_dptr == NULL) {
                        free(dbuf.dptr);
                }