does not compile on musl system (alpinelinux)
Closed this issue · 7 comments
In my case, gem install hiredis-client failed. As per chatgpt:
On Alpine Linux, the strnlen function is not included in musl by default, as it is part of the GNU C Library (glibc).
And solution given:
#include <string.h>
size_t strnlen(const char *s, size_t maxlen) {
return (strlen(s) < maxlen) ? strlen(s) : maxlen;
}
I wouldn't trust this ChatGPT answer one bit.
First because musl
does have strnlen
: https://github.com/cloudius-systems/musl/blob/00733dd1cf791d13ff6155509cf139a5f7b2eecb/src/string/strnlen.c
Second because the implementation provided by ChatGPT has a glaring read out of bound issue...
So please provide the error given to you by the compiler, or a way to reproduce the issue (e.g. a Dockerfile).
Sorry, I should have been more specific. So I am running:
$ gem install hiredis-client
On Linux version 6.11.2-arch1-1 (linux@archlinux) (gcc (GCC) 14.2.1 20240910, GNU ld (GNU Binutils) 2.43.0) #1 SMP PREEMPT_DYNAMIC Fri, 04 Oct 2024 21:51:11 +0000
Outcome:
Building native extensions. This could take a while...
ERROR: Error installing hiredis-client:
ERROR: Failed to build gem native extension.
current directory: /home/reduser/.local/share/gem/ruby/3.3.0/gems/hiredis-client-0.22.2/ext/redis_client/hiredis
/usr/bin/ruby extconf.rb
checking for openssl/ssl.h... yes
cc -std=c99 -pedantic -c -O3 -fPIC -fvisibility=hidden -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb alloc.c
cc -std=c99 -pedantic -c -O3 -fPIC -fvisibility=hidden -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb net.c
net.c: In function 'redisKeepAlive':
net.c:165:41: warning: unused parameter 'ttl' [-Wunused-parameter]
165 | int redisKeepAlive(redisContext *c, int ttl, int interval) {
| ~~~~^~~
net.c:165:50: warning: unused parameter 'interval' [-Wunused-parameter]
165 | int redisKeepAlive(redisContext *c, int ttl, int interval) {
| ~~~~^~~~~~~~
cc -std=c99 -pedantic -c -O3 -fPIC -fvisibility=hidden -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb hiredis.c
In file included from read.h:35,
from hiredis.h:36,
from hiredis.c:41:
In function 'sprintf',
inlined from 'redisvFormatCommand' at hiredis.c:498:11:
/usr/include/fortify/stdio.h:300:23: warning: '__orig_snprintf' specified size 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]
300 | __r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/fortify/string.h:26,
from hiredis.c:35:
/usr/include/fortify/stdio.h: In function 'redisvFormatCommand':
/usr/include/fortify/stdio.h:274:1: note: in a call to function '__orig_snprintf' declared with attribute 'access (read_only, 3)'
274 | _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n,
| ^~~~~~~~~~~
In function 'sprintf',
inlined from 'redisvFormatCommand' at hiredis.c:500:16:
/usr/include/fortify/stdio.h:300:23: warning: '__orig_snprintf' specified size 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]
300 | __r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/fortify/stdio.h: In function 'redisvFormatCommand':
/usr/include/fortify/stdio.h:274:1: note: in a call to function '__orig_snprintf' declared with attribute 'access (read_only, 3)'
274 | _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n,
| ^~~~~~~~~~~
In function 'sprintf',
inlined from 'redisFormatCommandArgv' at hiredis.c:647:11:
/usr/include/fortify/stdio.h:300:23: warning: '__orig_snprintf' specified size 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]
300 | __r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/fortify/stdio.h: In function 'redisFormatCommandArgv':
/usr/include/fortify/stdio.h:274:1: note: in a call to function '__orig_snprintf' declared with attribute 'access (read_only, 3)'
274 | _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n,
| ^~~~~~~~~~~
In function 'sprintf',
inlined from 'redisFormatCommandArgv' at hiredis.c:650:16:
/usr/include/fortify/stdio.h:300:23: warning: '__orig_snprintf' specified size 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]
300 | __r = __orig_snprintf(__s, __b, __f, __builtin_va_arg_pack());
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/fortify/stdio.h: In function 'redisFormatCommandArgv':
/usr/include/fortify/stdio.h:274:1: note: in a call to function '__orig_snprintf' declared with attribute 'access (read_only, 3)'
274 | _FORTIFY_FN(snprintf) int snprintf(char *__s, size_t __n,
| ^~~~~~~~~~~
cc -std=c99 -pedantic -c -O3 -fPIC -fvisibility=hidden -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb sds.c
cc -std=c99 -pedantic -c -O3 -fPIC -fvisibility=hidden -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb async.c
cc -std=c99 -pedantic -c -O3 -fPIC -fvisibility=hidden -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb read.c
cc -std=c99 -pedantic -c -O3 -fPIC -fvisibility=hidden -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb sockcompat.c
ar rcs libhiredis.a alloc.o net.o hiredis.o sds.o async.o read.o sockcompat.o
cc -std=c99 -pedantic -c -O3 -fPIC -fvisibility=hidden -Wall -W -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers -g -ggdb ssl.c
In file included from ssl.c:38:
/usr/include/fortify/string.h: In function 'strncat':
/usr/include/fortify/string.h:297:36: error: implicit declaration of function 'strnlen'; did you mean 'strlen'? [-Wimplicit-function-declaration]
297 | __fh_size_t __sl = strnlen(__s, __n);
| ^~~~~~~
| strlen
make: *** [Makefile:223: ssl.o] Error 1
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers. Check the mkmf.log file for more details. You may
need configuration options.
Provided configuration options:
--with-opt-dir
--without-opt-dir
--with-opt-include=${opt-dir}/include
--without-opt-include
--with-opt-lib=${opt-dir}/lib
--without-opt-lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=/usr/bin/$(RUBY_BASE_NAME)
--with-openssl-dir
--without-openssl-dir
--with-openssl-include=${openssl-dir}/include
--without-openssl-include
--with-openssl-lib=${openssl-dir}/lib
--without-openssl-lib
--with-make-prog
--without-make-prog
extconf.rb:51:in `block in build_hiredis': Building hiredis failed (RuntimeError)
from extconf.rb:49:in `chdir'
from extconf.rb:49:in `build_hiredis'
from extconf.rb:20:in `configure_extension'
from extconf.rb:12:in `configure'
from extconf.rb:108:in `<main>'
To see why this extension failed to compile, please check the mkmf.log which can be found here:
/home/reduser/.local/share/gem/ruby/3.3.0/extensions/x86_64-linux-musl/3.3.0/hiredis-client-0.22.2/mkmf.log
extconf failed, exit code 1
Gem files will remain installed in /home/reduser/.local/share/gem/ruby/3.3.0/gems/hiredis-client-0.22.2 for inspection.
Results logged to /home/reduser/.local/share/gem/ruby/3.3.0/extensions/x86_64-linux-musl/3.3.0/hiredis-client-0.22.2/gem_make.out
mkmf.log:
have_header: checking for openssl/ssl.h... -------------------- yes
LD_LIBRARY_PATH=.:/usr/lib "gcc -o conftest -I/usr/include/ruby-3.3.0/x86_64-linux-musl -I/usr/include/ruby-3.3.0/ruby/backward -I/usr/include/ruby-3.3.0 -I. -fno-omit-frame-pointer -fno-strict-aliasing -O2 -fstack-clash-protection -Wformat -Werror=format-security -fno-plt -g -fno-omit-frame-pointer -fno-strict-aliasing -fPIC conftest.c -L. -L/usr/lib -L. -Wl,--as-needed,-O1,--sort-common -Wl,-z,pack-relative-relocs -fstack-protector-strong -rdynamic -Wl,-export-dynamic -Wl,--no-as-needed -lruby -lm -lpthread -lucontext -lc"
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: int main(int argc, char **argv)
4: {
5: return !!argv[argc];
6: }
/* end */
LD_LIBRARY_PATH=.:/usr/lib "gcc -I/usr/include/ruby-3.3.0/x86_64-linux-musl -I/usr/include/ruby-3.3.0/ruby/backward -I/usr/include/ruby-3.3.0 -I. -fno-omit-frame-pointer -fno-strict-aliasing -O2 -fstack-clash-protection -Wformat -Werror=format-security -fno-plt -g -fno-omit-frame-pointer -fno-strict-aliasing -fPIC -c conftest.c"
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include <openssl/ssl.h>
/* end */
--------------------
Let me know if you need anything further.
Thanks for the extra information. Is there any way I can run the same environment? Alpine is generally used for docker images, is that what you are doing? If so could I know which base image you are using?
If not, how did you install alpine? From which .iso
etc.
I have it in lxd container.
$lxc launch images:alpine/edge test1
$lxc exec test1 /bin/ash
I guess you can easily get iso for VM (https://www.alpinelinux.org/downloads/)
Updated: use edge and create test1 container
upon further investigation, I noticed that for some reasons string.h is taken from /usr/include/fortify/string.h
which does not have strnlen()
but /usr/include/string.h
has strnlen()
.
Alright, I tried to repro using the alpine:edge
docker image on aarch64
.
$ apk add ruby ruby-dev gcc fortify-headers make git musl-dev openssl-dev
$ bundle
$ bundle exec rake compile
And it worked fine.
I specifically added fortify-headers
so that /usr/include/fortify/string.h
would be present, but yet it didn't break it.
That said:
In file included from ssl.c:38:
/usr/include/fortify/string.h: In function 'strncat':
/usr/include/fortify/string.h:297:36: error: implicit declaration of function 'strnlen'; did you mean 'strlen'? [-Wimplicit-function-declaration]
297 | __fh_size_t __sl = strnlen(__s, __n);
| ^~~~~~~
|
That error doesn't seem to actually be in redis-client
. The error is in that fortify
header thing, and when I look at the header in the alpine:edge
image it's only 192
lines long, so I suspect the version you are using got some recent changes and introduced a bug.
Yup: https://git.2f30.org/fortify-headers/commit/6573631a5e4339a2fc2f86680e36e35e25bf416c.html
Seems like it was fixed upstream.