Bug 844513: Add AddressSanitizer annotations to port_ArenaZeroAfterMark. NSS_3_15_BETA3
authorWan-Teh Chang <wtc@google.com>
Tue, 30 Apr 2013 16:06:47 -0700
changeset 10749 3986289106f1b63df43e46162764ef1865b06afb
parent 10748 b3a240eef440582a8a1a13d4fdb65a3e603cfe09
child 10750 22d622a0274d7ba63042153bcabc1c77d29bd3ec
push id59
push userwtc@google.com
push dateTue, 30 Apr 2013 23:07:01 +0000
bugs844513
Bug 844513: Add AddressSanitizer annotations to port_ArenaZeroAfterMark. Reset an arena mark to NULL after releasing the mark. r=choller.
lib/util/secasn1d.c
lib/util/secport.c
--- a/lib/util/secasn1d.c
+++ b/lib/util/secasn1d.c
@@ -2767,16 +2767,17 @@ SEC_ASN1DecoderUpdate (SEC_ASN1DecoderCo
 				 * be a good thing, I think), we need to
 				 * keep track of every place/pointer that
 				 * was allocated and make sure to NULL it
 				 * out before we then free back to the mark.	
 				 */
 	if (cx->their_pool != NULL) {
 	    PORT_Assert (cx->their_mark != NULL);
 	    PORT_ArenaRelease (cx->their_pool, cx->their_mark);
+	    cx->their_mark = NULL;
 	}
 #endif
 	return SECFailure;
     }
 
 #if 0	/* XXX This is what I want, but cannot have because it seems we
 	 * have situations (like when downloading a pkcs7 cert chain from
 	 * some issuers) that give us a total length which is greater than
--- a/lib/util/secport.c
+++ b/lib/util/secport.c
@@ -389,35 +389,55 @@ PORT_ArenaMark(PLArenaPool *arena)
 	PZ_Unlock(pool->lock);
     } else {
 	/* a "pure" NSPR arena */
 	result = PL_ARENA_MARK(arena);
     }
     return result;
 }
 
+/*
+ * This function accesses the internals of PLArena, which is why it needs
+ * to use the NSPR internal macro PL_MAKE_MEM_UNDEFINED before the memset
+ * calls.
+ *
+ * We should move this function to NSPR as PL_ClearArenaAfterMark or add
+ * a PL_ARENA_CLEAR_AND_RELEASE macro.
+ *
+ * TODO: remove the #ifdef PL_MAKE_MEM_UNDEFINED tests when NSPR 4.10+ is
+ * widely available.
+ */
 static void
 port_ArenaZeroAfterMark(PLArenaPool *arena, void *mark)
 {
     PLArena *a = arena->current;
     if (a->base <= (PRUword)mark && (PRUword)mark <= a->avail) {
 	/* fast path: mark falls in the current arena */
+#ifdef PL_MAKE_MEM_UNDEFINED
+	PL_MAKE_MEM_UNDEFINED(mark, a->avail - (PRUword)mark);
+#endif
 	memset(mark, 0, a->avail - (PRUword)mark);
     } else {
 	/* slow path: need to find the arena that mark falls in */
 	for (a = arena->first.next; a; a = a->next) {
 	    PR_ASSERT(a->base <= a->avail && a->avail <= a->limit);
 	    if (a->base <= (PRUword)mark && (PRUword)mark <= a->avail) {
+#ifdef PL_MAKE_MEM_UNDEFINED
+		PL_MAKE_MEM_UNDEFINED(mark, a->avail - (PRUword)mark);
+#endif
 		memset(mark, 0, a->avail - (PRUword)mark);
 		a = a->next;
 		break;
 	    }
 	}
 	for (; a; a = a->next) {
 	    PR_ASSERT(a->base <= a->avail && a->avail <= a->limit);
+#ifdef PL_MAKE_MEM_UNDEFINED
+	    PL_MAKE_MEM_UNDEFINED((void *)a->base, a->avail - a->base);
+#endif
 	    memset((void *)a->base, 0, a->avail - a->base);
 	}
     }
 }
 
 static void
 port_ArenaRelease(PLArenaPool *arena, void *mark, PRBool zero)
 {