summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <knielsen@ymer.(none)>2007-03-09 23:37:33 +0100
committerunknown <knielsen@ymer.(none)>2007-03-09 23:37:33 +0100
commitf5c27523fcbb572c7a4936a2ab58c247e03f2ea4 (patch)
treea2b4f27bca94d5aeef464fe850ec41e162247ab4
parent07fa209b6cc313bb98951f3aa9272d6b73c483f9 (diff)
downloadmariadb-git-f5c27523fcbb572c7a4936a2ab58c247e03f2ea4.tar.gz
BUG#27018: Partial blob write inside blob clobbers data after the write.
When doing partial blob update with NdbBlob::writeData(), zero-padding after the write was wrongly done, causing part of the old blob value to be overwritten with zeros (or spaces for text field). Fixed by only padding when needed (when writing at end of the blob). ndb/src/ndbapi/NdbBlob.cpp: Do not pad rest of blob part after the write, unless it is a write at the end of the blob. ndb/test/ndbapi/testBlobs.cpp: Add test case.
-rw-r--r--ndb/src/ndbapi/NdbBlob.cpp4
-rw-r--r--ndb/test/ndbapi/testBlobs.cpp54
2 files changed, 56 insertions, 2 deletions
diff --git a/ndb/src/ndbapi/NdbBlob.cpp b/ndb/src/ndbapi/NdbBlob.cpp
index 00b7441a37c..f0e6bf2e720 100644
--- a/ndb/src/ndbapi/NdbBlob.cpp
+++ b/ndb/src/ndbapi/NdbBlob.cpp
@@ -800,7 +800,9 @@ NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
DBUG_RETURN(-1);
Uint32 n = thePartSize - off;
if (n > len) {
- memset(thePartBuf.data + off + len, theFillChar, n - len);
+ /* If we are adding data at the end, fill rest of part. */
+ if (pos + len >= theLength)
+ memset(thePartBuf.data + off + len, theFillChar, n - len);
n = len;
}
memcpy(thePartBuf.data + off, buf, n);
diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp
index 81072f6a12a..bc703d64f21 100644
--- a/ndb/test/ndbapi/testBlobs.cpp
+++ b/ndb/test/ndbapi/testBlobs.cpp
@@ -138,6 +138,7 @@ printusage()
<< " 2 readData / writeData" << endl
<< "bug tests (no blob test)" << endl
<< " -bug 4088 ndb api hang with mixed ops on index table" << endl
+ << " -bug 27018 middle partial part write clobbers rest of part" << endl
<< " -bug nnnn delete + write gives 626" << endl
<< " -bug nnnn acc crash on delete and long key" << endl
;
@@ -1807,6 +1808,56 @@ bugtest_4088()
}
static int
+bugtest_27018()
+{
+ DBG("bug test 27018 - middle partial part write clobbers rest of part");
+
+ // insert rows
+ calcTups(false);
+ CHK(insertPk(false) == 0);
+ // new trans
+ for (unsigned k= 0; k < g_opt.m_rows; k++)
+ {
+ Tup& tup= g_tups[k];
+
+ CHK((g_con= g_ndb->startTransaction()) != 0);
+ CHK((g_opr= g_con->getNdbOperation(g_opt.m_tname)) != 0);
+ CHK(g_opr->updateTuple() == 0);
+ CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
+ if (g_opt.m_pk2len != 0)
+ CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+ CHK(getBlobHandles(g_opr) == 0);
+ CHK(g_con->execute(NoCommit) == 0);
+
+ /* Update one byte in random position. */
+ Uint32 offset= urandom(tup.m_blob1.m_len);
+ tup.m_blob1.m_buf[0]= 0xff ^ tup.m_blob1.m_val[offset];
+ CHK(g_bh1->setPos(offset) == 0);
+ CHK(g_bh1->writeData(&(tup.m_blob1.m_buf[0]), 1) == 0);
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+
+ CHK((g_con= g_ndb->startTransaction()) != 0);
+ CHK((g_opr= g_con->getNdbOperation(g_opt.m_tname)) != 0);
+ CHK(g_opr->readTuple() == 0);
+ CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
+ if (g_opt.m_pk2len != 0)
+ CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+ CHK(getBlobHandles(g_opr) == 0);
+
+ CHK(g_bh1->getValue(tup.m_blob1.m_buf, tup.m_blob1.m_len) == 0);
+ CHK(g_con->execute(Commit) == 0);
+ Uint64 len= ~0;
+ CHK(g_bh1->getLength(len) == 0 && len == tup.m_blob1.m_len);
+ tup.m_blob1.m_buf[offset]^= 0xff;
+ CHK(memcmp(tup.m_blob1.m_buf, tup.m_blob1.m_val, tup.m_blob1.m_len) == 0);
+ g_ndb->closeTransaction(g_con);
+ }
+
+ return 0;
+}
+
+static int
bugtest_2222()
{
return 0;
@@ -1822,7 +1873,8 @@ static struct {
int m_bug;
int (*m_test)();
} g_bugtest[] = {
- { 4088, bugtest_4088 }
+ { 4088, bugtest_4088 },
+ { 27018, bugtest_27018 }
};
NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)