Bug 808217 - Sporadic failure of 'certutil' to convert ASCII cert request to binary, additional patch, r=wtc NSS_3_15_BETA5
authorKai Engert <kaie@kuix.de>
Sat, 18 May 2013 05:43:32 +0200
changeset 10778 d0cf1feff4dc491d14a1691f7aae42d886676593
parent 10777 c63c14c95855138b68cf48d385e0ac95b29f3f02
child 10779 9359778f76e02f1b79a719608930c94bfda54d18
push id87
push userkaie@kuix.de
push dateSat, 18 May 2013 03:43:40 +0000
reviewerswtc
bugs808217
Bug 808217 - Sporadic failure of 'certutil' to convert ASCII cert request to binary, additional patch, r=wtc
cmd/bltest/blapitest.c
cmd/lib/secutil.c
lib/util/nssutil.def
lib/util/secitem.c
lib/util/secitem.h
--- a/cmd/bltest/blapitest.c
+++ b/cmd/bltest/blapitest.c
@@ -1028,18 +1028,17 @@ bltestCopyIO(PLArenaPool *arena, bltestI
 }
 
 void
 misalignBuffer(PLArenaPool *arena, bltestIO *io, int off)
 {
     ptrdiff_t offset = (ptrdiff_t)io->buf.data % WORDSIZE;
     int length = io->buf.len;
     if (offset != off) {
-	SECITEM_ReallocItem(arena, &io->buf, length, length + 2*WORDSIZE);
-	io->buf.len = length + 2*WORDSIZE; /* why doesn't realloc do this? */
+	SECITEM_ReallocItemV2(arena, &io->buf, length + 2*WORDSIZE);
 	/* offset may have changed? */
 	offset = (ptrdiff_t)io->buf.data % WORDSIZE;
 	if (offset != off) {
 	    memmove(io->buf.data + off, io->buf.data, length);
 	    io->pBuf.data = io->buf.data + off;
 	    io->pBuf.len = length;
 	} else {
 	    io->pBuf.data = io->buf.data;
--- a/cmd/lib/secutil.c
+++ b/cmd/lib/secutil.c
@@ -525,17 +525,17 @@ SECU_ReadDERFromFile(SECItem *der, PRFil
 		*trailer = '\0';
 	    if (!body || !trailer) {
 		fprintf(stderr, "input has header but no trailer\n");
 		PORT_Free(filedata.data);
 		return SECFailure;
 	    }
 	} else {
 	    /* need one additional byte for zero terminator */
-	    rv = SECITEM_ReallocItem(NULL, &filedata, filedata.len, filedata.len+1);
+	    rv = SECITEM_ReallocItemV2(NULL, &filedata, filedata.len+1);
 	    if (rv != SECSuccess) {
 		PORT_Free(filedata.data);
 		return rv;
 	    }
 	    body = (char*)filedata.data;
 	    body[filedata.len-1] = '\0';
 	}
      
--- a/lib/util/nssutil.def
+++ b/lib/util/nssutil.def
@@ -261,12 +261,13 @@ NSSUTIL_QuoteSize;
 ;+    local:
 ;+       *;
 ;+};
 ;+NSSUTIL_3.15 {         # NSS Utilities 3.15 release
 ;+    global:
 SECITEM_AllocArray;
 SECITEM_DupArray;
 SECITEM_FreeArray;
+SECITEM_ReallocItemV2;
 SECITEM_ZfreeArray;
 ;+    local:
 ;+       *;
 ;+};
--- a/lib/util/secitem.c
+++ b/lib/util/secitem.c
@@ -110,16 +110,73 @@ SECITEM_ReallocItem(PLArenaPool *arena, 
 
     if (item->data == NULL) {
 	return SECFailure;
     }
 
     return SECSuccess;
 }
 
+SECStatus
+SECITEM_ReallocItemV2(PLArenaPool *arena, SECItem *item, unsigned int newlen)
+{
+    unsigned char *newdata = NULL;
+
+    PORT_Assert(item);
+    if (!item) {
+	PORT_SetError(SEC_ERROR_INVALID_ARGS);
+	return SECFailure;
+    }
+    
+    if (item->len == newlen) {
+	return SECSuccess;
+    }
+
+    if (!newlen) {
+	SECITEM_FreeItem(item, PR_FALSE);
+	return SECSuccess;
+    }
+    
+    if (!item->len) {
+	/* allocate fresh block of memory */
+	PORT_Assert(!item->data);
+	if (arena) {
+	    newdata = PORT_ArenaAlloc(arena, newlen);
+	} else {
+	    newdata = PORT_Alloc(newlen);
+	}
+    } else {
+	/* reallocate or adjust existing block of memory */
+	if (arena) {
+	    if (item->len > newlen) {
+		/* There's no need to realloc a shorter block from the arena,
+		 * because it would result in using even more memory!
+		 * Therefore we'll continue to use the old block and 
+		 * set the item to the shorter size.
+		 */
+		item->len = newlen;
+		return SECSuccess;
+	    } else {
+		newdata = PORT_ArenaGrow(arena, item->data, item->len, newlen);
+	    }
+	} else {
+	    newdata = PORT_Realloc(item->data, newlen);
+	}
+    }
+
+    if (!newdata) {
+	PORT_SetError(SEC_ERROR_NO_MEMORY);
+	return SECFailure;
+    }
+
+    item->len = newlen;
+    item->data = newdata;
+    return SECSuccess;
+}
+
 SECComparison
 SECITEM_CompareItem(const SECItem *a, const SECItem *b)
 {
     unsigned m;
     int rv;
 
     if (a == b)
     	return SECEqual;
--- a/lib/util/secitem.h
+++ b/lib/util/secitem.h
@@ -31,27 +31,45 @@ SEC_BEGIN_PROTOS
 **
 ** XXX This probably should take a SECItemType, but since that is mostly
 ** unused and our improved APIs (aka Stan) are looming, I left it out.
 */
 extern SECItem *SECITEM_AllocItem(PLArenaPool *arena, SECItem *item,
 				  unsigned int len);
 
 /*
+** This is a legacy function containing bugs. It doesn't update item->len,
+** and it has other issues as described in bug 298649 and bug 298938.
+** However, the function is  kept unchanged for consumers that might depend 
+** on the broken behaviour. New code should call SECITEM_ReallocItemV2.
+**
 ** Reallocate the data for the specified "item".  If "arena" is not NULL,
 ** then reallocate from there, otherwise reallocate from the heap.
 ** In the case where oldlen is 0, the data is allocated (not reallocated).
 ** In any case, "item" is expected to be a valid SECItem pointer;
 ** SECFailure is returned if it is not.  If the allocation succeeds,
 ** SECSuccess is returned.
 */
-extern SECStatus SECITEM_ReallocItem(PLArenaPool *arena, SECItem *item,
+extern SECStatus SECITEM_ReallocItem( /* deprecated function */
+				     PLArenaPool *arena, SECItem *item,
 				     unsigned int oldlen, unsigned int newlen);
 
 /*
+** Reallocate the data for the specified "item".  If "arena" is not NULL,
+** then reallocate from there, otherwise reallocate from the heap.
+** If the item already has at least the request new size,
+** then the item is kept unchanged and SECSuccess is returned.
+** In any case, "item" is expected to be a valid SECItem pointer;
+** SECFailure is returned if it is not, and the item will remain unchanged.
+** If the allocation succeeds, the item is updated and SECSuccess is returned.
+ */
+extern SECStatus SECITEM_ReallocItemV2(PLArenaPool *arena, SECItem *item,
+				       unsigned int newlen);
+
+/*
 ** Compare two items returning the difference between them.
 */
 extern SECComparison SECITEM_CompareItem(const SECItem *a, const SECItem *b);
 
 /*
 ** Compare two items -- if they are the same, return true; otherwise false.
 */
 extern PRBool SECITEM_ItemsAreEqual(const SECItem *a, const SECItem *b);