Skip to content

Commit

Permalink
builtin.inc: fix build with -Woverlength-strings
Browse files Browse the repository at this point in the history
C99 only allows string literals with length up to 4095 characters.

This patch introduces a gen_jq_builtins generator program that generates
the jq_builtins array in builtin.c as an array literal instead of a
string literal to make compilation not fail when building with
-Woverlength-strings.

Add -Woverlength-strings to CFLAGS to verify that the fix works.

Also introduce HOSTCC autoconf variable to get a C compiler to build
gen_jq_builtin on the host when cross-compiling.

Fixes #1481
  • Loading branch information
emanuele6 committed Dec 11, 2023
1 parent 90eb699 commit 189586c
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 35 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ jobs:
--with-oniguruma=builtin \
--enable-static \
--enable-all-static \
HOSTCC=c99 \
CFLAGS="-O2 -pthread -fstack-protector-all"
make -j"$(nproc)"
file ./jq
Expand Down Expand Up @@ -159,6 +160,7 @@ jobs:
--with-oniguruma=builtin \
--enable-static \
--enable-all-static \
HOSTCC=c99 \
CFLAGS="-O2 -pthread -fstack-protector-all"
make -j"$(sysctl -n hw.logicalcpu)"
strip ./jq
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ jq
!tests/modules/lib/jq/
jq.1

# Generator programs
src/gen_jq_builtins

# Generated source
src/builtin.inc
src/config_opts.inc
Expand Down
20 changes: 14 additions & 6 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ LIBJQ_SRC = src/builtin.c src/bytecode.c src/compile.c src/execute.c \

### C build options

AM_CFLAGS = -Wextra -Wall -Wno-unused-parameter -Wno-unused-function
AM_CFLAGS = -Wextra -Wall -Woverlength-strings

AM_CFLAGS += -Wno-unused-parameter -Wno-unused-function

if WIN32
AM_CFLAGS += -municode
Expand Down Expand Up @@ -117,12 +119,17 @@ src/config_opts.inc:
fi | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' -e 's/^/#define JQ_CONFIG /' > $@
src/main.c: src/version.h src/config_opts.inc

src/builtin.inc: $(srcdir)/src/builtin.jq
mkdir -p src
$(AM_V_GEN) sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' $(srcdir)/src/builtin.jq > $@
src/gen_jq_builtins: $(srcdir)/src/gen_jq_builtins.c
@mkdir -p src
@printf ' HOSTCC %s\n' $@
@$(HOSTCC) $(DEFS) -o $@ $<
src/builtin.inc: src/gen_jq_builtins $(srcdir)/src/builtin.jq
@mkdir -p src
$(AM_V_GEN)src/gen_jq_builtins $(srcdir)/src/builtin.jq > $@
src/builtin.o: src/builtin.inc

CLEANFILES = src/version.h .remake-version-h src/builtin.inc src/config_opts.inc
CLEANFILES = src/version.h .remake-version-h src/config_opts.inc \
src/gen_jq_builtins src/builtin.inc

bin_PROGRAMS = jq
jq_SOURCES = src/main.c src/version.h
Expand Down Expand Up @@ -228,7 +235,8 @@ EXTRA_DIST = $(DOC_FILES) $(man_MANS) $(TESTS) $(TEST_LOG_COMPILER) \
tests/optional.test tests/man.test tests/manonig.test \
tests/jq.test tests/onig.test tests/base64.test \
tests/utf8-truncate.jq tests/jq-f-test.sh \
tests/no-main-program.jq tests/yes-main-program.jq
tests/no-main-program.jq tests/yes-main-program.jq \
src/gen_jq_builtins.c

AM_DISTCHECK_CONFIGURE_FLAGS=--with-oniguruma=builtin

Expand Down
6 changes: 3 additions & 3 deletions compile-ios.sh
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,15 @@ cd "${builddir}/"

# ./configure; make install
cd "${builddir}/onig-${oniguruma}"
CC=${CC} LDFLAGS=${LDFLAGS} \
HOSTCC=${HOSTCC:-c99} CC=${CC} LDFLAGS=${LDFLAGS} \
./configure --host=${HOST} --build=$(./config.guess) --enable-shared=no --enable-static=yes --prefix=/
make -j${MAKEJOBS} install DESTDIR="${cwd}/ios/onig/${arch}"
make clean

# Jump back to JQ.
cd ${cwd}
[[ ! -f ./configure ]] && autoreconf -ivf
CC=${CC} LDFLAGS=${LDFLAGS} \
HOSTCC=${HOSTCC:-c99} CC=${CC} LDFLAGS=${LDFLAGS} \
./configure --host=${HOST} --build=$(./config/config.guess) --enable-docs=no --enable-shared=no --enable-static=yes --prefix=/ --with-oniguruma=${cwd}/ios/onig/${arch} $(test -z ${BISON+x} || echo '--enable-maintainer-mode')
make -j${MAKEJOBS} install DESTDIR="${cwd}/ios/jq/${arch}"
make clean
Expand Down
4 changes: 4 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ AM_PROG_CC_C_O

AC_SYS_LARGEFILE # issue 2167

AC_ARG_VAR([HOSTCC], [Host compiler; necessary to build gen_jq_builtins when cross-compiling])
HOSTCC=${HOSTCC:-$CC}
AC_DEFINE([HOSTCC], ["$HOSTCC"])

dnl couldn't use AM_PROG_LEX as it doesn't support header files like the
dnl AC_PROG_YACC macros...

Expand Down
2 changes: 1 addition & 1 deletion scripts/crosscompile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ esac
rm -rf "$plat/tmp"
mkdir "$plat/tmp"
cd "$plat/tmp"
../../../configure "$@"
../../../configure "HOSTCC=${HOSTCC:-c99}" "$@"
make "$jobs" DESTDIR=$plat install
set -x
for jq in `find . -type f \( -name jq -o -name jq.exe \) -print`; do
Expand Down
25 changes: 0 additions & 25 deletions src/builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -1798,33 +1798,8 @@ static block bind_bytecoded_builtins(block b) {
static const char jq_builtins[] =
/* Include jq-coded builtins */
#include "src/builtin.inc"

/* Include unsupported math functions next */
#define LIBM_DD(name)
#define LIBM_DDD(name)
#define LIBM_DDDD(name)
#define LIBM_DD_NO(name) "def " #name ": \"Error: " #name "/0 not found at build time\"|error;"
#define LIBM_DDD_NO(name) "def " #name "(a;b): \"Error: " #name "/2 not found at build time\"|error;"
#define LIBM_DDDD_NO(name) "def " #name "(a;b;c): \"Error: " #name "/3 not found at build time\"|error;"
#include "libm.h"
#ifndef HAVE_FREXP
"def frexp: \"Error: frexp/0 not found at build time\"|error;"
#endif
#ifndef HAVE_MODF
"def modf: \"Error: modf/0 not found at build time\"|error;"
#endif
#ifndef HAVE_LGAMMA_R
"def lgamma_r: \"Error: lgamma_r/0 not found at build time\"|error;"
#endif
;

#undef LIBM_DDDD_NO
#undef LIBM_DDD_NO
#undef LIBM_DD_NO
#undef LIBM_DDDD
#undef LIBM_DDD
#undef LIBM_DD

static block gen_builtin_list(block builtins) {
jv list = jv_array_append(block_list_funcs(builtins, 1), jv_string("builtins/0"));
return BLOCK(builtins, gen_function("builtins", gen_noop(), gen_const(list)));
Expand Down
132 changes: 132 additions & 0 deletions src/gen_jq_builtins.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include "main-win32.h"
#include "math-macos.h"

static uint_least8_t index = 0;

static bool indentation(void) {
if (index == 0 && fputs(" ", stdout) == EOF) {
perror("fputs");
return false;
}
return true;
}

static bool separator(void) {
if (putchar(index < 10 ? ' ' : '\n') == EOF) {
perror("putchar");
return false;
}
index = (index + 1) % 11;
return true;
}

static bool gen_char(char const ch) {
if (!indentation())
return false;
if (printf("%.4o,", (unsigned)ch) == EOF)
return false;
return separator();
}

static bool gen_string(char const *const string)
{
for (char const *ch = string; *ch; ++ch) {
if (!gen_char(*ch))
return false;
}
return true;
}

static bool gen_file(FILE *const fp) {
for (int ch; (ch = getc(fp)) != EOF;) {
if (!gen_char(ch))
return false;
}
if (ferror(fp)) {
perror("getc");
return false;
}
return true;
}

DEFINE_MAIN(int argc, char *const argv[]) {
/* argv[1] must be the path to "src/builtin.jq" */
if (argc != 2) {
static char const err[] =
"gen_builtin_inc: Wrong number of arguments.\n";
if (fputs(err, stderr) == EOF)
perror("fputs");
return EXIT_FAILURE;
}

if (puts("{") == EOF) {
perror("puts");
return EXIT_FAILURE;
}

FILE *const builtin_jq = fopen(argv[1], "r");
if (!builtin_jq) {
perror("fopen");
return EXIT_FAILURE;
}
if (!gen_file(builtin_jq))
return EXIT_FAILURE;

#define GEN_STRING(string) \
do { \
if (!gen_string(string)) \
return EXIT_FAILURE; \
} while (0)

/* Unsupported math functions */
#define LIBM_DD(name)
#define LIBM_DDD(name)
#define LIBM_DDDD(name)
#define LIBM_DD_NO(name) \
gen_string( \
"def " #name ":" \
"\"Error: " #name "/0 not found at build time\"|error;");
#define LIBM_DDD_NO(name) \
gen_string( \
"def " #name "(a;b):" \
"\"Error: " #name "/2 not found at build time\"|error;");
#define LIBM_DDDD_NO(name) \
gen_string("def " #name "(a;b;c):" \
"\"Error: " #name "/3 not found at build time\"|error;");
#include "libm.h"
#undef LIBM_DD
#undef LIBM_DDD
#undef LIBM_DDDD
#undef LIBM_DD_NO
#undef LIBM_DDD_NO
#undef LIBM_DDDD_NO

#ifndef HAVE_FREXP
GEN_STRING(
"def frexp:"
"\"Error: frexp/0 not found at build time\"|error;");
#endif
#ifndef HAVE_MODF
GEN_STRING(
"def modf:"
"\"Error: modf/0 not found at build time\"|error;");
#endif
#ifndef HAVE_LGAMMA_R
GEN_STRING(
"def lgamma_r:"
"\"Error: lgamma_r/0 not found at build time\"|error;");
#endif

#undef GEN_STRING

if (puts("'\\0',\n}") == EOF) {
perror("puts");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

0 comments on commit 189586c

Please sign in to comment.