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)