diff --git a/libc/stdio/vsnprintf.c b/libc/stdio/vsnprintf.c
index b2f0b94..b9435b8 100644
--- a/libc/stdio/vsnprintf.c
+++ b/libc/stdio/vsnprintf.c
@@ -22,59 +22,99 @@ static const unsigned long long convert[] = {
 	0xFFFFFFFFFFULL, 0xFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL
 };
 
+static int
+print_str_fill(char **buffer, size_t bufsize, char *sizec,
+					const char *str, char c)
+{
+	int i, sizei, len;
+	char *bstart = *buffer;
 
+	sizei = strtoul(sizec, NULL, 10);
+	len = strlen(str);
+	if (sizei > len) {
+		for (i = 0;
+			(i < (sizei - len)) && ((*buffer - bstart) < bufsize);
+									i++) {
+			**buffer = c;
+			*buffer += 1;
+		}
+	}
+	return 1;
+}
 
 static int
-print_itoa(char **buffer, unsigned long value, unsigned short base, bool upper)
+print_str(char **buffer, size_t bufsize, const char *str)
+{
+	char *bstart = *buffer;
+	int i;
+
+	for (i = 0; (i < strlen(str)) && ((*buffer - bstart) < bufsize); i++) {
+		**buffer = str[i];
+		*buffer += 1;
+	}
+	return 1;
+}
+
+static unsigned int __attrconst
+print_intlen(unsigned long value, unsigned short int base)
+{
+	int i = 0;
+
+	while (value > 0) {
+		value /= base;
+		i++;
+	}
+	if (i == 0)
+		i = 1;
+	return i;
+}
+
+static int
+print_itoa(char **buffer, size_t bufsize, unsigned long value,
+					unsigned short base, bool upper)
 {
 	const char zeichen[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
 	char c;
-	int i = 0;
-	char tmp[16];
+	int i, len;
 
 	if(base <= 2 || base > 16)
 		return 0;
 
+	len = i = print_intlen(value, base);
+
+	/* Don't print to buffer if bufsize is not enough. */
+	if (len > bufsize)
+		return 0;
+
 	do {
 		c = zeichen[value % base];
 		if (upper)
 			c = toupper(c);
-		tmp[i++] = c;
+
+		(*buffer)[--i] = c;
 		value /= base;
 	} while(value);
 
-	while (i--) {
-		**buffer = tmp[i];
-		*buffer += 1;
-	}
+	*buffer += len;
 
 	return 1;
 }
 
 
-static unsigned int __attrconst
-print_intlen(unsigned long value, unsigned short int base)
-{
-	int i = 0;
-
-	while(value > 0) {
-		value /= base;
-		i++;
-	}
-	if(i == 0) i = 1;
-	return i;
-}
-
 
 static int
-print_fill(char **buffer, char *sizec, unsigned long size, unsigned short int base, char c, int optlen)
+print_fill(char **buffer, size_t bufsize, char *sizec, unsigned long size,
+				unsigned short int base, char c, int optlen)
 {
 	int i, sizei, len;
+	char *bstart = *buffer;
 
 	sizei = strtoul(sizec, NULL, 10);
  	len = print_intlen(size, base) + optlen;
-	if(sizei > len) {
-		for(i = 0; i < (sizei - len); i++) {
+	if (sizei > len) {
+		for (i = 0;
+			(i < (sizei - len)) && ((*buffer - bstart) < bufsize);
+									i++) {
 			**buffer = c;
 			*buffer += 1;
 		}
@@ -85,10 +125,10 @@ print_fill(char **buffer, char *sizec, unsigned long size, unsigned short int ba
 
 
 static int
-print_format(char **buffer, const char *format, void *var)
+print_format(char **buffer, size_t bufsize, const char *format, void *var)
 {
-	unsigned long start;
-	unsigned int i = 0, sizei = 0, len = 0, length_mod = sizeof(int);
+	char *start;
+	unsigned int i = 0, length_mod = sizeof(int);
 	unsigned long value = 0;
 	unsigned long signBit;
 	char *form, sizec[32];
@@ -96,7 +136,7 @@ print_format(char **buffer, const char *format, void *var)
 	bool upper = false;
 
 	form  = (char *) format;
-	start = (unsigned long) *buffer;
+	start = *buffer;
 
 	form++;
 	if(*form == '0' || *form == '.') {
@@ -104,7 +144,7 @@ print_format(char **buffer, const char *format, void *var)
 		form++;
 	}
 
-	while(*form != '\0') {
+	while ((*form != '\0') && ((*buffer - start) < bufsize)) {
 		switch(*form) {
 			case 'u':
 			case 'd':
@@ -117,53 +157,54 @@ print_format(char **buffer, const char *format, void *var)
 					*buffer += 1;
 					value = (-(unsigned long)value) & convert[length_mod];
 				}
-				print_fill(buffer, sizec, value, 10, sign, 0);
-				print_itoa(buffer, value, 10, upper);
+				print_fill(buffer, bufsize - (*buffer - start),
+						sizec, value, 10, sign, 0);
+				print_itoa(buffer, bufsize - (*buffer - start),
+							value, 10, upper);
 				break;
 			case 'X':
 				upper = true;
 			case 'x':
 				sizec[i] = '\0';
 				value = (unsigned long) var & convert[length_mod];
-				print_fill(buffer, sizec, value, 16, sign, 0);
-				print_itoa(buffer, value, 16, upper);
+				print_fill(buffer, bufsize - (*buffer - start),
+						sizec, value, 16, sign, 0);
+				print_itoa(buffer, bufsize - (*buffer - start),
+							value, 16, upper);
 				break;
 			case 'O':
 			case 'o':
 				sizec[i] = '\0';
 				value = (long int) var & convert[length_mod];
-				print_fill(buffer, sizec, value, 8, sign, 0);
-				print_itoa(buffer, value, 8, upper);
+				print_fill(buffer, bufsize - (*buffer - start),
+						sizec, value, 8, sign, 0);
+				print_itoa(buffer, bufsize - (*buffer - start),
+							value, 8, upper);
 				break;
 			case 'p':
 				sizec[i] = '\0';
-				print_fill(buffer, sizec, (unsigned long) var, 16, ' ', 2);
-				**buffer = '0';
-				*buffer += 1;	
-				**buffer = 'x';
-				*buffer += 1;
-				print_itoa(buffer,(unsigned long) var, 16, upper);
+				print_fill(buffer, bufsize - (*buffer - start),
+					sizec, (unsigned long) var, 16, ' ', 2);
+				print_str(buffer, bufsize - (*buffer - start),
+									"0x");
+				print_itoa(buffer, bufsize - (*buffer - start),
+						(unsigned long) var, 16, upper);
 				break;
 			case 'c':
 				sizec[i] = '\0';
-				print_fill(buffer, sizec, 1, 10, ' ', 0);
+				print_fill(buffer, bufsize - (*buffer - start),
+							sizec, 1, 10, ' ', 0);
 				**buffer = (unsigned long) var;
 				*buffer += 1;
 				break;
 			case 's':
 				sizec[i] = '\0';
-				sizei = strtoul(sizec, NULL, 10);
-				len = strlen((char *) var);
-				if(sizei > len) {
-					for(i = 0; i < (sizei - len); i++) {
-						**buffer = ' ';
-						*buffer += 1;
-					}
-				}
-				for(i = 0; i < strlen((char *) var); i++) {
-					**buffer = ((char *) var)[i];
-					*buffer += 1;
-				}
+				print_str_fill(buffer,
+					bufsize - (*buffer - start), sizec,
+							(char *) var, ' ');
+
+				print_str(buffer, bufsize - (*buffer - start),
+								(char *) var);
 				break;
 			case 'l':
 				form++;
@@ -210,6 +251,16 @@ vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg)
 	bstart = buffer;
 	ptr = (char *) format;
 
+	/*
+	 * Return from here if size passed is zero, otherwise we would
+	 * overrun buffer while setting NULL character at the end.
+	 */
+	if (!buffer || !bufsize)
+		return 0;
+
+	/* Leave one space for NULL character */
+	bufsize--;
+
 	while(*ptr != '\0' && (buffer - bstart) < bufsize)
 	{
 		if(*ptr == '%') {
@@ -228,7 +279,9 @@ vsnprintf(char *buffer, size_t bufsize, const char *format, va_list arg)
 			if(*ptr == '%') {
 				*buffer++ = '%';
 			} else {
-				print_format(&buffer, formstr, va_arg(arg, void *));
+				print_format(&buffer,
+					bufsize - (buffer - bstart),
+					formstr, va_arg(arg, void *));
 			}
 			ptr++;
 		} else {
