git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Timo Sirainen <tss@iki.fi>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: git@vger.kernel.org
Subject: Re: Buffer overflows
Date: Fri, 31 Aug 2007 08:00:30 +0300	[thread overview]
Message-ID: <1188536430.29782.903.camel@hurina> (raw)
In-Reply-To: <alpine.LFD.0.999.0708302050170.25853@woody.linux-foundation.org>


[-- Attachment #1.1: Type: text/plain, Size: 1889 bytes --]

On Thu, 2007-08-30 at 21:09 -0700, Linus Torvalds wrote:
> 
> On Fri, 31 Aug 2007, Timo Sirainen wrote:
> > > 
> > > Perhaps because your patch was using a totally nonstandard and slow
> > > interface, and had nasty string declaration issues, as people even pointed
> > > out to you.
> > 
> > Slow?
> 
> Having a string library, and then implementing "str_append()" with a 
> strlen() sounds pretty disgusting to me. 
> 
> Gcc could have optimized the strlen() away for constant string arguments, 
> but since you made the thing out-of-line, it can't do that any more.
> 
> So yes, I bet there are faster string libraries out there.

Oh, well that's easy to fix. But I don't think the speed matters much in
string manipulation, it's usually not done in performance critical
paths.

> > The code should be easy to verify to be secure, and with some kind of a safe
> > string API it's a lot easier than trying to figure out corner cases where
> > strcpy() calls break.
> 
> I actually looked at the patches, and the "stringbuf()" thing was just too 
> ugly to live. It was also nonportable, in that you use the reserved 
> namespace (which we do extensively in the kernel, but that's an 
> "embdedded" application that doesn't use system header files).
> 
> So the API was anything but "safe".

Some of those were fixed in the patch I sent at the beginning of this
thread. But since you asked, attached is yet another version of it. As
far as I know it's fully C99 compatible. Would be C89 but there's that
va_copy() call.

I guess it could still be optimized more, but at least strlen() is now
in a macro. :)

Or if you don't like the STR_STATIC() macro, another way would be:

#define STR_STATIC_INIT(buf) { buf, sizeof(buf), 0, }

char static_buf[1024];
struct string str = STR_STATIC_INIT(static_buf);

str_append(&str, "hello world");


[-- Attachment #1.2: git-strings.diff --]
[-- Type: text/x-patch, Size: 3063 bytes --]

--- /dev/null	2007-07-12 03:40:41.165212167 +0300
+++ str.h	2007-08-31 07:35:04.000000000 +0300
@@ -0,0 +1,33 @@
+#ifndef STR_H
+#define STR_H
+
+struct string {
+	char *buf;
+
+	unsigned int alloc_size;
+	unsigned int len;
+
+	unsigned int malloced:1;
+	unsigned int overflowed:1;
+};
+
+#define STR_STATIC(name, size) \
+	struct { \
+	  struct string str; \
+	  char string_buf[(size) + 1]; \
+	} name = { { (name).string_buf, sizeof((name).string_buf), 0, } }
+
+extern struct string *str_alloc(unsigned int initial_size);
+extern void str_free(struct string **str);
+
+extern void str_append_n(struct string *str, const char *cstr,
+			 unsigned int len);
+extern void str_printfa(struct string *str, const char *fmt, ...)
+	__attribute__((format (printf, 2, 3)));
+extern void str_truncate(struct string *str, unsigned int len);
+
+#define str_append(str, cstr) str_append_n(str, cstr, strlen(cstr))
+#define str_c(str) ((str)->buf)
+#define str_len(str) ((str)->len)
+
+#endif
--- /dev/null	2007-07-12 03:40:41.165212167 +0300
+++ str.c	2007-08-31 07:36:56.000000000 +0300
@@ -0,0 +1,85 @@
+#include "str.h"
+#include "git-compat-util.h"
+
+struct string *str_alloc(unsigned int initial_size)
+{
+	struct string *str;
+
+	str = xcalloc(sizeof(*str), 1);
+	str->alloc_size = initial_size + 1;
+	str->buf = xmalloc(str->alloc_size);
+	str->buf[0] = '\0';
+	return str;
+}
+
+void str_free(struct string **_str)
+{
+	struct string *str = *_str;
+
+	if (str->malloced)
+		free(str->buf);
+	str->buf = NULL;
+	free(str);
+
+	*_str = NULL;
+}
+
+static void str_grow_if_needed(struct string *str, unsigned int *len)
+{
+	unsigned int avail = str->alloc_size - str->len;
+
+	if (*len >= avail) {
+		if (!str->malloced) {
+			/* static buffer size */
+			*len = avail;
+			str->overflowed = 1;
+		} else {
+			str->alloc_size = (str->len + *len) * 2;
+			str->buf = xrealloc(str->buf, str->alloc_size);
+		}
+	}
+}
+
+void str_append_n(struct string *str, const char *cstr, unsigned int len)
+{
+	str_grow_if_needed(str, &len);
+	memcpy(str->buf + str->len, cstr, len);
+	str->len += len;
+	str->buf[str->len] = '\0';
+}
+
+void str_printfa(struct string *str, const char *fmt, ...)
+{
+	unsigned int len, avail = str->alloc_size - str->len;
+	va_list va, va2;
+	int ret;
+
+	va_start(va, fmt);
+	va_copy(va2, va);
+	ret = vsnprintf(str->buf + str->len, avail, fmt, va);
+	assert(ret >= 0);
+
+	if ((unsigned int)ret >= avail) {
+		if (!str->malloced) {
+			str->overflowed = 1;
+			ret = avail == 0 ? 0 : avail-1;
+		} else {
+			len = ret;
+			str_grow_if_needed(str, &len);
+			avail = str->alloc_size - str->len;
+
+			ret = vsnprintf(str->buf + str->len, avail, fmt, va2);
+			assert(ret >= 0 && (unsigned int)ret < avail);
+		}
+	}
+	str->len += ret;
+	va_end(va);
+}
+
+void str_truncate(struct string *str, unsigned int len)
+{
+	if (len >= str->alloc_size)
+		len = str->alloc_size - 1;
+	str->len = len;
+	str->buf[len] = '\0';
+}

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

  reply	other threads:[~2007-08-31  5:00 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-08-30 19:26 Buffer overflows Timo Sirainen
2007-08-30 20:26 ` Lukas Sandström
2007-08-30 20:46 ` Linus Torvalds
2007-08-30 21:08   ` Timo Sirainen
2007-08-30 21:35     ` Reece Dunn
2007-08-30 21:51       ` Timo Sirainen
2007-08-30 22:34         ` Reece Dunn
2007-08-31 10:52           ` Wincent Colaiuta
2007-08-31 12:48             ` Simon 'corecode' Schubert
2007-08-30 22:14       ` Junio C Hamano
2007-08-30 22:36         ` Pierre Habouzit
2007-08-30 22:41         ` Timo Sirainen
2007-09-02 13:42         ` Johan Herland
2007-09-02 15:11           ` Reece Dunn
2007-09-02 15:19             ` David Kastrup
2007-09-02 15:35               ` Reece Dunn
2007-09-03  0:19               ` Jakub Narebski
2007-09-03  0:31                 ` Junio C Hamano
2007-09-02 17:17           ` René Scharfe
2007-09-02 17:39             ` Lukas Sandström
2007-08-31  4:09     ` Linus Torvalds
2007-08-31  5:00       ` Timo Sirainen [this message]
2007-08-31  9:53         ` Andreas Ericsson
2007-08-31 10:06         ` Johannes Schindelin
2007-08-30 21:48 ` [PATCH] Temporary fix for stack smashing in mailinfo Alex Riesen
2007-08-30 22:53   ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1188536430.29782.903.camel@hurina \
    --to=tss@iki.fi \
    --cc=git@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).