arc4random

411 views
Skip to first unread message

Dirk Vanden Boer

unread,
Sep 16, 2017, 7:08:07 AM9/16/17
to emscripten-discuss
I'm trying to compile expat with emscripten, it fails on an arc4random call however.

/usr/local/Cellar/emscripten/1.37.18/libexec/emcc -DHAVE_EXPAT_CONFIG_H @CMakeFiles/expat.dir/includes_C.rsp -fno-strict-aliasing -DNDEBUG -O2 -fPIC -o CMakeFiles/expat.dir/lib/xmlparse.c.o -c xmlparse.c
xmlparse
.c:852:31: error: implicit declaration of function 'arc4random' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
const uint32_t random32 = arc4random();

The expat configure step detected arc4random however:
-- Looking for arc4random
-- Looking for arc4random - found

xmlparse.c includes both <stdlib.h> and <stdio.h>


However I see this test case in the emscripten repo:
def test_arc4random(self):
    open
('src.c', 'w').write(r'''
#include <stdlib.h>
#include <stdio.h>
int main() {
  printf("%d\n", arc4random());
  printf("%d\n", arc4random());
}
    '''
)
    check_execute
([PYTHON, EMCC, 'src.c', '-Wno-implicit-function-declaration'])

So it seems like it should work. What am I missing?

Jukka Jylänki

unread,
Sep 18, 2017, 9:07:24 AM9/18/17
to emscripte...@googlegroups.com
Searching for arc4random in Emscripten codebase gives:

Searching 7677 files for "arc4random"

c:\code\emsdk\emscripten\incoming\src\deps_info.json:
2: "arc4random": ["rand"],

c:\code\emsdk\emscripten\incoming\src\library.js:
796: // For compatibility, call to rand() when code requests
arc4random(), although this is *not* at all
797: // as strong as rc4 is. See
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/arc4random.3.html
798: arc4random: 'rand',

c:\code\emsdk\emscripten\incoming\system\include\libcxx\__config:
215: // Certain architectures provide arc4random(). Prefer using
216: // arc4random() over /dev/{u,}random to make it possible to obtain

c:\code\emsdk\emscripten\incoming\system\lib\libcxx\random.cpp:
53: return arc4random();

c:\code\emsdk\emscripten\incoming\tests\test_other.py:
7205: def test_arc4random(self):
7211: printf("%d\n", arc4random());
7212: printf("%d\n", arc4random());

10 matches across 5 files

so it looks like we do have some support for that, by routing to
calling rand() directly. You can try if deleting line 798 "arc4random:
'rand'," in src/library.js will make expat configure not find
arc4random, and try a proper fallback foute.

Note in particular that there does not exist a declaration of this
function in any Emscripten headers. That is, Emscripten implements the
function in src/library.js, but does not declare it in headers. Trying
to trace the root source of this function finds
- https://linux.die.net/man/3/arc4random
- https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/arc4random.3.html
- https://man.openbsd.org/arc4random

where it looks like this is a BSD specific standard library function.
You can also try adding a manual declaration of "uint32_t
arc4random(void);" to someplace appropriate. (perhaps first hack that
line in to system/include/libc/stdlib.h" to see if that fixes it,
though that will not be an appropriate permanent place).
> --
> You received this message because you are subscribed to the Google Groups
> "emscripten-discuss" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to emscripten-disc...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Dirk Vanden Boer

unread,
Sep 18, 2017, 10:03:37 AM9/18/17
to emscripten-discuss
I patched the expat source to include the declaration of the arc4random function. That allows it to compile.
Seems like emscripten should provide the declaration though if it provides the implementation. Otherwise every project that uses the cmake infrastructure to detect this function (check_function_exists) is going to run into trouble.

Thanks for the hint.

Jukka Jylänki

unread,
Sep 18, 2017, 11:32:48 AM9/18/17
to emscripte...@googlegroups.com
2017-09-18 17:03 GMT+03:00 Dirk Vanden Boer <dirk...@gmail.com>:
> I patched the expat source to include the declaration of the arc4random
> function. That allows it to compile.
> Seems like emscripten should provide the declaration though if it provides
> the implementation. Otherwise every project that uses the cmake
> infrastructure to detect this function (check_function_exists) is going to
> run into trouble.

That might not be the root cause here for the configure script
tripping itself up. Did you try if deleting the implementation line in
src/library.js would also have fixed the configure script to run as
expected?

If we did provide the declaration, we would not be able to add it to
<stdlib.h>, because that would be nonstandard. We could do a #include
<bsd/stdlib.h> that https://linux.die.net/man/3/arc4random suggests,
but unless expat configure script was aware of this, that would not
help either, so some changes to expat may be necessary whatever the
appropriate fix would be.

Dirk Vanden Boer

unread,
Sep 18, 2017, 2:10:58 PM9/18/17
to emscripten-discuss
I commented out the
arc4random: 'rand',
line in library.js

This causes the expat configure to not find arc4random and the build succeeds.

Why are you providing the arc4random definition if it is not part of the c standard library? Bsd compatibility?

Jukka Jylänki

unread,
Sep 18, 2017, 2:58:00 PM9/18/17
to emscripte...@googlegroups.com
The implementation of arc4random comes from this ancient commit from
February 2013: https://github.com/kripken/emscripten/commit/a5c78a58902abd6166a81a895cc9eea141c9cab4.
There is no grand reason behind supporting it, and there doesn't exist
a BSD compatibility layer of any kind in general (this single function
is probably the BSD compatibility layer). I believe the history comes
from a configure script of some other library having needed it, and it
was just added in.

Searching further,
https://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/html_node/libc_13.html
suggests that there exists a #define _BSD_SOURCE, which also states

"If your program defines _BSD_SOURCE, you must give the option
`-lbsd-compat' to the compiler or linker when linking the program, to
tell it to find functions in this special compatibility library before
looking for them in the normal C library. "

so that machinery could also be used to gate in 4.3 BSD compatibility
code. Would that solve expat's problem out of the box? I.e. is it
aware of GCC's #define _BSD_SOURCE and -lbsd-compat?

Dirk Vanden Boer

unread,
Sep 18, 2017, 3:08:23 PM9/18/17
to emscripten-discuss
I think it would solve expat's problem because the arc4random detection code will not define _BSD_SOURCE on a non BSD system.So it will not detect the presence of the arc4random function and will not try to use it.
Reply all
Reply to author
Forward
0 new messages