shithub: scc

Download patch

ref: faa82abe38fca557949e44a1745039e39ee5f232
parent: 895c2c914ce5ea912b0f1818bc173d7aadbee32e
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Sep 14 10:19:07 EDT 2021

libc: Fix malloc() in linux

Linux brk() syscall does not follow the SUSv2 behaviour.
SUSv2 mandates brk() to return an integer that indicates
if the syscall was correct or not, but Linux returns the
previous heap in case of error. Sbrk() in malloc.c   was
trying to solve that problem with a weird comparision,
that generated an integer to pointer conversion, because
the prototype of _brk() was returning integer but   the
actual syscall was returning a pointer, truncating the
value to 32 bits. This patch adds a wrapper over the Linux
syscall and ry to keep the portable code to the SUSv2
interface.

--- /dev/null
+++ b/src/libc/arch/linux/Makefile
@@ -1,0 +1,12 @@
+.POSIX:
+PROJECTDIR = ../../../..
+include $(PROJECTDIR)/scripts/rules.mk
+include ../../rules.mk
+
+OBJS=\
+	_brk.$O\
+	_getheap.$O\
+
+all: $(OBJS)
+
+include deps.mk
--- /dev/null
+++ b/src/libc/arch/linux/_brk.c
@@ -1,0 +1,16 @@
+#include <errno.h>
+#include <stddef.h>
+
+#include "../../libc.h"
+#include "../../syscall.h"
+#include "brk.h"
+
+int
+_brk(void *addr)
+{
+	if (_sys_brk(addr) != addr) {
+		errno = ENOMEM;
+		return -1;
+	}
+	return 0;
+}
--- a/src/libc/arch/linux/_getheap.c
+++ b/src/libc/arch/linux/_getheap.c
@@ -2,9 +2,10 @@
 
 #include "../../libc.h"
 #include "../../syscall.h"
+#include "brk.h"
 
 void *
 _getheap(void)
 {
-	return _brk(0);
+	return _sys_brk(0);
 }
--- /dev/null
+++ b/src/libc/arch/linux/brk.h
@@ -1,0 +1,2 @@
+extern void *_sys_brk(void *);
+
--- /dev/null
+++ b/src/libc/arch/linux/deps.mk
@@ -1,0 +1,5 @@
+#deps
+./_brk.o: ./../../libc.h
+./_brk.o: ./../../syscall.h
+./_getheap.o: ./../../libc.h
+./_getheap.o: ./../../syscall.h
--- a/src/libc/stdlib/malloc.c
+++ b/src/libc/stdlib/malloc.c
@@ -75,7 +75,6 @@
 sbrk(uintptr_t inc)
 {
 	char *new, *old;
-	void *p;
 	static void *heap;
 
 	if (!heap)
@@ -86,8 +85,7 @@
 		return ERRADDR;
 
 	new = old + inc;
-	p = _brk(new);
-	if (p == old || p == ERRADDR)
+	if (_brk(new) < 0)
 		return ERRADDR;
 	heap = new;