Re: git: 2c709ee70ade - main - libc: handle zero alignment in memalign()
Date: Sat, 25 Feb 2023 22:29:52 UTC
Ed Maste wrote in
<CAPyFy2A-dnbrivwZiFoJv4sYL9qyXvoZX2SK-bcd9pEdf30qQg@mail.gmail.com>:
|On Fri, 24 Feb 2023 at 20:27, Steffen Nurpmeso <steffen@sdaoden.eu> wrote:
|> Me too. 'Was just thinking of allocators which give back valid
|> but inaccessible memory for 0 bytes so that each access would
|> fault.
|
|The size is not (necessarily) zero though. The alignment requested is.
I personally would fail EINVAL for 0: something really must be
bogus if you reqest an alignment of 0. The standard says
Upon successful completion, posix_memalign( ) shall return zero;
otherwise, an error number shall be returned to indicate the error
and the contents of memptr shall either be left unmodified or be
set to a null pointer.
If size is 0, either:
. posix_memalign( ) shall not attempt to allocate any space, in
which case either an implementation-defined error number shall
be returned, or zero shall be returned with a null pointer
returned in memptr, or
. posix_memalign( ) shall attempt to allocate some space and, if
the allocation succeeds, zero shall be returned and a pointer
to the allocated space shall be returned in memptr. The
application shall ensure that the pointer is not used to
access an object.
The latter is hard (expensive, special-cased) to implement (here).
Also the claim of the commit message was wrong:
The address of the allocated memory will be a multiple of
alignment, which must be a power of two and a multiple of
sizeof(void *).
As can be seen:
#?0|kent:tmp$ cat t.c; for i in $(seq 8); do tcc -run t.c $i;echo $?;done
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv){
char *vp;
int err;
if(!(err = posix_memalign((void**)&vp, atoi(argv[1]), 1))){
if(vp)
*vp = '\0';
else
printf("x1\n");
}else
printf("x2: %s\n",strerror(err));
return err != 0;
}
x2: Invalid argument
1
x2: Invalid argument
1
x2: Invalid argument
1
x2: Invalid argument
1
x2: Invalid argument
1
x2: Invalid argument
1
x2: Invalid argument
1
0
On the other "size" is ok:
#?0|kent:tmp$ cat t.c; for i in $(seq 0 2); do tcc -run t.c $i;echo $?;done
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv){
char *vp;
int err;
if(!(err = posix_memalign((void**)&vp, 8, atoi(argv[1])))){
if(vp)
*vp = '\0';
else
printf("x1\n");
}else
printf("x2: %s\n",strerror(err));
return err != 0;
}
0
0
Yet it is not because *vp is accessible, contradicting the
standard -- no?
(Exaggerating a bit, but the last two weeks for me and GNU:
iconv(3) is special for ILSEQ on output [non-conforming],
sysconf(3) PROCESSORS_ONLN is wrong in cgroup
[echo 1-3 > /sys/fs/cgroup/NAME/cpuset.cpus], causing
over-thread-usage in programs like xz and zstd [seems wrong and
implementation-specific non-conforming], whereas those using
nproc(1) are right, and now posix_memalign().)
Ciao, and a nice Sunday everone (who can)!
--steffen
|
|Der Kragenbaer, The moon bear,
|der holt sich munter he cheerfully and one by one
|einen nach dem anderen runter wa.ks himself off
|(By Robert Gernhardt)