Date: Mon, 7 Apr 2008 17:31:36 +0200 From: Felix von Leitner To: hyc (at) symas.com Subject: regarding http://www.openldap.org/lists/openldap-devel/200804/msg00005.html Message-ID: <20080407153136.GB25688@codeblau.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.13 (2006-08-11) Status: RO Content-Length: 1211 Lines: 41 Please forward this to the openldap mailing list. It is important to educate as many people as possible about the issue. Sorry, Howard, but you missed the point. This is about doing an overflow check, not a bounds check. Let me illustrate the issue. - you get a char*, ptr, and a size_t, len. - you want to do a bounds check typical code: if (ptr+len > max) return EINVAL; max, in this context, is a char* pointing to the byte beyond the last valid byte in the buffer. It turns out: this check is not sufficient. If len is really big, it can cause ptr+len to point to an address that is actually LOWER in memory than ptr. This is called an address overflow, and the problem is closely related to integer overflows. To catch this condition, you need to do a check like this: if (ptr+len < ptr || ptr+len > max) return EINVAL; Note that it is NOT sufficient to check whether (long)len<0 !! The problem is: gcc will, in this context, optimize out the first part of the check, leaving the whole bounds check defeated. This is particularly problematic in binary protocols like ASN.1 DER as used by LDAP, where the protocol can transfer arbitrarily large length values. Thanks, Felix