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;