diff mbox series

[meta-oe] jq: fix build with gcc-15

Message ID 20250325135112.2028029-1-martin.jansa@gmail.com
State Accepted
Headers show
Series [meta-oe] jq: fix build with gcc-15 | expand

Commit Message

Martin Jansa March 25, 2025, 1:51 p.m. UTC
From: Martin Jansa <martin.jansa@gmail.com>

* backport 3 commits to fix:
  http://errors.yoctoproject.org/Errors/Details/848831/

../jq-1.7.1/src/builtin.c:1705:4: error: initialization of 'jv (*)(void)' from incompatible pointer type 'jv (*)(jq_state *, jv)' [-Wincompatible-pointer-types]
 1705 |   {f_ ## name,  #name, 1},
      |    ^~

Signed-off-by: Martin Jansa <martin.jansa@gmail.com>
---
 ...c-fix-build-with-Woverlength-strings.patch | 215 +++++++++++++++
 ...-add-and-use-LIBM_DA-and-LIBM_DA_NO-.patch | 164 ++++++++++++
 ...eck-builtin-cfunctions-in-function_l.patch | 249 ++++++++++++++++++
 meta-oe/recipes-devtools/jq/jq_1.7.1.bb       |   3 +
 4 files changed, 631 insertions(+)
 create mode 100644 meta-oe/recipes-devtools/jq/jq/0001-builtin.c-fix-build-with-Woverlength-strings.patch
 create mode 100644 meta-oe/recipes-devtools/jq/jq/0002-libm.h-builtin.c-add-and-use-LIBM_DA-and-LIBM_DA_NO-.patch
 create mode 100644 meta-oe/recipes-devtools/jq/jq/0003-builtin.c-typecheck-builtin-cfunctions-in-function_l.patch

Comments

Khem Raj March 26, 2025, 2:45 p.m. UTC | #1
I am seeing ptest failures with jq with this patch

On Tue, Mar 25, 2025 at 6:51 AM Martin Jansa via
lists.openembedded.org <martin.jansa=gmail.com@lists.openembedded.org>
wrote:
>
> From: Martin Jansa <martin.jansa@gmail.com>
>
> * backport 3 commits to fix:
>   http://errors.yoctoproject.org/Errors/Details/848831/
>
> ../jq-1.7.1/src/builtin.c:1705:4: error: initialization of 'jv (*)(void)' from incompatible pointer type 'jv (*)(jq_state *, jv)' [-Wincompatible-pointer-types]
>  1705 |   {f_ ## name,  #name, 1},
>       |    ^~
>
> Signed-off-by: Martin Jansa <martin.jansa@gmail.com>
> ---
>  ...c-fix-build-with-Woverlength-strings.patch | 215 +++++++++++++++
>  ...-add-and-use-LIBM_DA-and-LIBM_DA_NO-.patch | 164 ++++++++++++
>  ...eck-builtin-cfunctions-in-function_l.patch | 249 ++++++++++++++++++
>  meta-oe/recipes-devtools/jq/jq_1.7.1.bb       |   3 +
>  4 files changed, 631 insertions(+)
>  create mode 100644 meta-oe/recipes-devtools/jq/jq/0001-builtin.c-fix-build-with-Woverlength-strings.patch
>  create mode 100644 meta-oe/recipes-devtools/jq/jq/0002-libm.h-builtin.c-add-and-use-LIBM_DA-and-LIBM_DA_NO-.patch
>  create mode 100644 meta-oe/recipes-devtools/jq/jq/0003-builtin.c-typecheck-builtin-cfunctions-in-function_l.patch
>
> diff --git a/meta-oe/recipes-devtools/jq/jq/0001-builtin.c-fix-build-with-Woverlength-strings.patch b/meta-oe/recipes-devtools/jq/jq/0001-builtin.c-fix-build-with-Woverlength-strings.patch
> new file mode 100644
> index 0000000000..cd7cdba00c
> --- /dev/null
> +++ b/meta-oe/recipes-devtools/jq/jq/0001-builtin.c-fix-build-with-Woverlength-strings.patch
> @@ -0,0 +1,215 @@
> +From 8707f8764dfc470d1974eb1d613f5a4bec3610ac Mon Sep 17 00:00:00 2001
> +From: Emanuele Torre <torreemanuele6@gmail.com>
> +Date: Fri, 26 Jan 2024 04:42:11 +0100
> +Subject: [PATCH] builtin.c: fix build with -Woverlength-strings
> +
> +C99 only allows string literals long at most 4095 characters.
> +jq_builtins was a lot longer than that.
> +
> +I rewrote all the optional libm error stubs in C so the value of
> +jq_builtins is not build dependent.
> +
> +I replaced the command that generates builtin.inc with a POSIX compliant
> +od|sed command that encodes builtin.jq as a comma delimited list of
> +octal numbers (that can be embedded in C using a {} literal).
> +
> +I also added -Woverlength-strings to AM_CFLAGS to verify that the
> +problem is fixed.
> +
> +Fixes #1481
> +Upstream-Status: Backport [605836b builtin.c: fix build with -Woverlength-strings]
> +Signed-off-by: Martin Jansa <martin.jansa@gmail.com>
> +---
> +
> + Makefile.am   | 10 ++++--
> + src/builtin.c | 86 ++++++++++++++++++++++++---------------------------
> + 2 files changed, 48 insertions(+), 48 deletions(-)
> +
> +diff --git a/Makefile.am b/Makefile.am
> +index 76e35df..f1f9f2e 100644
> +--- a/Makefile.am
> ++++ b/Makefile.am
> +@@ -19,7 +19,8 @@ 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 -Wno-unused-parameter -Wno-unused-function \
> ++            -Woverlength-strings
> +
> + if WIN32
> + AM_CFLAGS += -municode
> +@@ -119,7 +120,12 @@ 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 > $@
> ++      $(AM_V_GEN) od -v -A n -t o1 -- $< | \
> ++      sed -e 's/$$/ /' \
> ++          -e 's/\([0123456789]\) /\1, /g' \
> ++          -e 's/ $$//' \
> ++          -e 's/ 0/  0/g' \
> ++          -e 's/ \([123456789]\)/ 0\1/g' > $@
> + src/builtin.o: src/builtin.inc
> +
> + CLEANFILES = src/version.h .remake-version-h src/builtin.inc src/config_opts.inc
> +diff --git a/src/builtin.c b/src/builtin.c
> +index 902490d..a3ce7e4 100644
> +--- a/src/builtin.c
> ++++ b/src/builtin.c
> +@@ -155,7 +155,11 @@ static jv f_ ## name(jq_state *jq, jv input) { \
> +   jv_free(input); \
> +   return ret; \
> + }
> +-#define LIBM_DD_NO(name)
> ++#define LIBM_DD_NO(name) \
> ++static jv f_ ## name(jq_state *jq, jv input) { \
> ++  jv error = jv_string("Error: " #name "/0 not found at build time"); \
> ++  return ret_error(input, error); \
> ++}
> +
> + #define LIBM_DDD(name) \
> + static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
> +@@ -173,7 +177,12 @@ static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
> +   jv_free(b); \
> +   return ret; \
> + }
> +-#define LIBM_DDD_NO(name)
> ++#define LIBM_DDD_NO(name) \
> ++static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
> ++  jv_free(b); \
> ++  jv error = jv_string("Error: " #name "/2 not found at build time"); \
> ++  return ret_error2(input, a, error); \
> ++}
> +
> + #define LIBM_DDDD(name) \
> + static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
> +@@ -199,7 +208,14 @@ static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
> +   jv_free(c); \
> +   return ret; \
> + }
> +-#define LIBM_DDDD_NO(name)
> ++#define LIBM_DDDD_NO(name) \
> ++static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
> ++  jv_free(c) \
> ++  jv_free(b); \
> ++  jv error = jv_string("Error: " #name "/3 not found at build time"); \
> ++  return ret_error2(input, a, error); \
> ++}
> ++
> + #include "libm.h"
> + #undef LIBM_DDDD_NO
> + #undef LIBM_DDD_NO
> +@@ -226,6 +242,11 @@ static jv f_frexp(jq_state *jq, jv input) {
> +   jv_free(input);
> +   return ret;
> + }
> ++#else
> ++static jv f_frexp(jq_state *jq, jv input) {
> ++  jv error = jv_string("Error: frexp/0 not found at build time");
> ++  return ret_error(input, error);
> ++}
> + #endif
> + #ifdef HAVE_MODF
> + static jv f_modf(jq_state *jq, jv input) {
> +@@ -237,6 +258,11 @@ static jv f_modf(jq_state *jq, jv input) {
> +   jv_free(input);
> +   return jv_array_append(ret, jv_number(i));
> + }
> ++#else
> ++static jv f_modf(jq_state *jq, jv input) {
> ++  jv error = jv_string("Error: modf/0 not found at build time");
> ++  return ret_error(input, error);
> ++}
> + #endif
> + #ifdef HAVE_LGAMMA_R
> + static jv f_lgamma_r(jq_state *jq, jv input) {
> +@@ -248,6 +274,11 @@ static jv f_lgamma_r(jq_state *jq, jv input) {
> +   jv_free(input);
> +   return jv_array_append(ret, jv_number(sign));
> + }
> ++#else
> ++static jv f_lgamma_r(jq_state *jq, jv input) {
> ++  jv error = jv_string("Error: lgamma_r/0 not found at build time");
> ++  return ret_error(input, error);
> ++}
> + #endif
> +
> + static jv f_negate(jq_state *jq, jv input) {
> +@@ -1703,27 +1734,21 @@ static jv f_current_line(jq_state *jq, jv a) {
> +
> + #define LIBM_DD(name) \
> +   {f_ ## name,  #name, 1},
> +-#define LIBM_DD_NO(name)
> ++#define LIBM_DD_NO(name) LIBM_DD(name)
> +
> + #define LIBM_DDD(name) \
> +   {f_ ## name, #name, 3},
> +-#define LIBM_DDD_NO(name)
> ++#define LIBM_DDD_NO(name) LIBM_DDD(name)
> +
> + #define LIBM_DDDD(name) \
> +   {f_ ## name, #name, 4},
> +-#define LIBM_DDDD_NO(name)
> ++#define LIBM_DDDD_NO(name) LIBM_DDDD(name)
> +
> + static const struct cfunction function_list[] = {
> + #include "libm.h"
> +-#ifdef HAVE_FREXP
> +   {f_frexp,"frexp", 1},
> +-#endif
> +-#ifdef HAVE_MODF
> +   {f_modf,"modf", 1},
> +-#endif
> +-#ifdef HAVE_LGAMMA_R
> +   {f_lgamma_r,"lgamma_r", 1},
> +-#endif
> +   {f_negate, "_negate", 1},
> + #define BINOP(name) {f_ ## name, "_" #name, 3},
> + BINOPS
> +@@ -1838,42 +1863,11 @@ static block bind_bytecoded_builtins(block b) {
> +   return BLOCK(builtins, b);
> + }
> +
> +-static const char jq_builtins[] =
> ++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
> +-
> +-#ifdef __APPLE__
> +-#undef HAVE_GAMMA
> +-#undef HAVE_EXP10
> +-#undef HAVE_DREM
> +-#undef HAVE_SIGNIFICAND
> +-#endif
> ++  '\0',
> ++};
> +
> + static block gen_builtin_list(block builtins) {
> +   jv list = jv_array_append(block_list_funcs(builtins, 1), jv_string("builtins/0"));
> diff --git a/meta-oe/recipes-devtools/jq/jq/0002-libm.h-builtin.c-add-and-use-LIBM_DA-and-LIBM_DA_NO-.patch b/meta-oe/recipes-devtools/jq/jq/0002-libm.h-builtin.c-add-and-use-LIBM_DA-and-LIBM_DA_NO-.patch
> new file mode 100644
> index 0000000000..68b8cb4f6e
> --- /dev/null
> +++ b/meta-oe/recipes-devtools/jq/jq/0002-libm.h-builtin.c-add-and-use-LIBM_DA-and-LIBM_DA_NO-.patch
> @@ -0,0 +1,164 @@
> +From c65e6fa48e6da30727c87ccdd88d8fb6a7a70f20 Mon Sep 17 00:00:00 2001
> +From: Emanuele Torre <torreemanuele6@gmail.com>
> +Date: Fri, 26 Jan 2024 11:26:57 +0100
> +Subject: [PATCH] libm.h+builtin.c: add and use LIBM_DA and LIBM_DA_NO macros
> +
> +For functions that from one double return an array with two numbers.
> +Upstream-Status: Backport [bd3c828 libm.h+builtin.c: add and use LIBM_DA and LIBM_DA_NO macros]
> +Signed-off-by: Martin Jansa <martin.jansa@gmail.com>
> +---
> + src/builtin.c | 78 ++++++++++++++++-----------------------------------
> + src/libm.h    | 15 ++++++++++
> + 2 files changed, 39 insertions(+), 54 deletions(-)
> +
> +diff --git a/src/builtin.c b/src/builtin.c
> +index a3ce7e4..9b71bca 100644
> +--- a/src/builtin.c
> ++++ b/src/builtin.c
> +@@ -216,13 +216,32 @@ static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
> +   return ret_error2(input, a, error); \
> + }
> +
> ++#define LIBM_DA(name, type) \
> ++static jv f_ ## name(jq_state *jq, jv input) { \
> ++  if (jv_get_kind(input) != JV_KIND_NUMBER) { \
> ++    return type_error(input, "number required"); \
> ++  } \
> ++  type value; \
> ++  double d = name(jv_number_value(input), &value); \
> ++  jv ret = JV_ARRAY(jv_number(d), jv_number(value)); \
> ++  jv_free(input); \
> ++  return ret; \
> ++}
> ++#define LIBM_DA_NO(name, type) \
> ++static jv f_ ## name(jq_state *jq, jv input) { \
> ++  jv error = jv_string("Error: " #name "/0 not found at build time"); \
> ++  return ret_error(input, error); \
> ++}
> ++
> + #include "libm.h"
> + #undef LIBM_DDDD_NO
> + #undef LIBM_DDD_NO
> + #undef LIBM_DD_NO
> ++#undef LIBM_DA_NO
> + #undef LIBM_DDDD
> + #undef LIBM_DDD
> + #undef LIBM_DD
> ++#undef LIBM_DA
> +
> + #ifdef __APPLE__
> + #undef gamma
> +@@ -231,56 +250,6 @@ static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
> + #undef exp10
> + #endif
> +
> +-#ifdef HAVE_FREXP
> +-static jv f_frexp(jq_state *jq, jv input) {
> +-  if (jv_get_kind(input) != JV_KIND_NUMBER) {
> +-    return type_error(input, "number required");
> +-  }
> +-  int exp;
> +-  double d = frexp(jv_number_value(input), &exp);
> +-  jv ret = JV_ARRAY(jv_number(d), jv_number(exp));
> +-  jv_free(input);
> +-  return ret;
> +-}
> +-#else
> +-static jv f_frexp(jq_state *jq, jv input) {
> +-  jv error = jv_string("Error: frexp/0 not found at build time");
> +-  return ret_error(input, error);
> +-}
> +-#endif
> +-#ifdef HAVE_MODF
> +-static jv f_modf(jq_state *jq, jv input) {
> +-  if (jv_get_kind(input) != JV_KIND_NUMBER) {
> +-    return type_error(input, "number required");
> +-  }
> +-  double i;
> +-  jv ret = JV_ARRAY(jv_number(modf(jv_number_value(input), &i)));
> +-  jv_free(input);
> +-  return jv_array_append(ret, jv_number(i));
> +-}
> +-#else
> +-static jv f_modf(jq_state *jq, jv input) {
> +-  jv error = jv_string("Error: modf/0 not found at build time");
> +-  return ret_error(input, error);
> +-}
> +-#endif
> +-#ifdef HAVE_LGAMMA_R
> +-static jv f_lgamma_r(jq_state *jq, jv input) {
> +-  if (jv_get_kind(input) != JV_KIND_NUMBER) {
> +-    return type_error(input, "number required");
> +-  }
> +-  int sign;
> +-  jv ret = JV_ARRAY(jv_number(lgamma_r(jv_number_value(input), &sign)));
> +-  jv_free(input);
> +-  return jv_array_append(ret, jv_number(sign));
> +-}
> +-#else
> +-static jv f_lgamma_r(jq_state *jq, jv input) {
> +-  jv error = jv_string("Error: lgamma_r/0 not found at build time");
> +-  return ret_error(input, error);
> +-}
> +-#endif
> +-
> + static jv f_negate(jq_state *jq, jv input) {
> +   if (jv_get_kind(input) != JV_KIND_NUMBER) {
> +     return type_error(input, "cannot be negated");
> +@@ -1733,8 +1702,10 @@ static jv f_current_line(jq_state *jq, jv a) {
> + }
> +
> + #define LIBM_DD(name) \
> +-  {f_ ## name,  #name, 1},
> ++  {f_ ## name, #name, 1},
> + #define LIBM_DD_NO(name) LIBM_DD(name)
> ++#define LIBM_DA(name, type) LIBM_DD(name)
> ++#define LIBM_DA_NO(name, type) LIBM_DD(name)
> +
> + #define LIBM_DDD(name) \
> +   {f_ ## name, #name, 3},
> +@@ -1746,9 +1717,6 @@ static jv f_current_line(jq_state *jq, jv a) {
> +
> + static const struct cfunction function_list[] = {
> + #include "libm.h"
> +-  {f_frexp,"frexp", 1},
> +-  {f_modf,"modf", 1},
> +-  {f_lgamma_r,"lgamma_r", 1},
> +   {f_negate, "_negate", 1},
> + #define BINOP(name) {f_ ## name, "_" #name, 3},
> + BINOPS
> +@@ -1813,9 +1781,11 @@ BINOPS
> + #undef LIBM_DDDD_NO
> + #undef LIBM_DDD_NO
> + #undef LIBM_DD_NO
> ++#undef LIBM_DA_NO
> + #undef LIBM_DDDD
> + #undef LIBM_DDD
> + #undef LIBM_DD
> ++#undef LIBM_DA
> +
> + struct bytecoded_builtin { const char* name; block code; };
> + static block bind_bytecoded_builtins(block b) {
> +diff --git a/src/libm.h b/src/libm.h
> +index 8efc1c5..7332bd8 100644
> +--- a/src/libm.h
> ++++ b/src/libm.h
> +@@ -289,3 +289,18 @@ LIBM_DDD(ldexp)
> + #else
> + LIBM_DDD_NO(ldexp)
> + #endif
> ++#ifdef HAVE_MODF
> ++LIBM_DA(modf, double)
> ++#else
> ++LIBM_DA_NO(modf, double)
> ++#endif
> ++#ifdef HAVE_FREXP
> ++LIBM_DA(frexp, int)
> ++#else
> ++LIBM_DA_NO(frexp, int)
> ++#endif
> ++#ifdef HAVE_LGAMMA_R
> ++LIBM_DA(lgamma_r, int)
> ++#else
> ++LIBM_DA_NO(lgamma_r, int)
> ++#endif
> diff --git a/meta-oe/recipes-devtools/jq/jq/0003-builtin.c-typecheck-builtin-cfunctions-in-function_l.patch b/meta-oe/recipes-devtools/jq/jq/0003-builtin.c-typecheck-builtin-cfunctions-in-function_l.patch
> new file mode 100644
> index 0000000000..f8b6c5baf6
> --- /dev/null
> +++ b/meta-oe/recipes-devtools/jq/jq/0003-builtin.c-typecheck-builtin-cfunctions-in-function_l.patch
> @@ -0,0 +1,249 @@
> +From 98839759a92e3ad41870bfc7415f0ecf320b5097 Mon Sep 17 00:00:00 2001
> +From: Emanuele Torre <torreemanuele6@gmail.com>
> +Date: Mon, 25 Nov 2024 07:47:14 +0100
> +Subject: [PATCH] builtin.c: typecheck builtin cfunctions in function_list
> +
> +In C23 (default C standard used by GCC 15),  jv (*fptr)();  has become
> +equivalent to  jv (*fptr)(void);  so we can no longer assign builtin
> +implemenations directly to the fptr member of cfunctions without
> +generating a compile error.
> +
> +Since there does not seem to be any straight-forward way to tell
> +autoconf to force the compiler to use C99 short of explicitly adding
> +-std=c99 to CFLAGS, it is probably a cleaner solution to just make the
> +code C23 compatible.
> +
> +A possible solution could have been to just redeclare  cfunction.fptr
> +as void*, but then the functions' return type would not have been type
> +checked (e.g. if you tried to add a {printf, "printf", 2}, where printf
> +is a function that does not return jv, the compiler wouldn't have
> +complained.)
> +We were already not typechecking the arguments of the functions, so e.g.
> +  {binop_plus, "_plus", 3},  /* instead of {f_plus, "_plus, 3},       */
> +  {f_setpath, "setpath", 4}, /* instead of {f_setpath, "setpath", 3}, */
> +compile without errors despite not having the correct prototype.
> +
> +So I thought of instead improving the situation by redefining
> +cfunction.fptr as a union of function pointers with the prototypes that
> +the jq bytecode interpreter can call, and use a macro to add the builtin
> +functions to function_list using to the arity argument to assign the
> +implementation function to the appropriate union member.
> +
> +Now the code won't compile if the wrong arity, or an arity not supported
> +by the bytecode interpreter (>5 = 1input+4arguments), or a prototype not
> +jallable by the bytecode interpreter (e.g. binop_plus that doesn't
> +expect a  jq_state*  argument).
> +
> +Also, the code now compiles with gcc -std=c23.
> +
> +Fixes #3206
> +Upstream-Status: Backport [0b82b38 builtin.c: typecheck builtin cfunctions in function_list]
> +Signed-off-by: Martin Jansa <martin.jansa@gmail.com>
> +---
> + src/builtin.c  | 126 +++++++++++++++++++++++++------------------------
> + src/bytecode.h |  11 +++--
> + src/execute.c  |  11 ++---
> + 3 files changed, 78 insertions(+), 70 deletions(-)
> +
> +diff --git a/src/builtin.c b/src/builtin.c
> +index 9b71bca..6ba6511 100644
> +--- a/src/builtin.c
> ++++ b/src/builtin.c
> +@@ -1701,82 +1701,83 @@ static jv f_current_line(jq_state *jq, jv a) {
> +   return jq_util_input_get_current_line(jq);
> + }
> +
> ++#define CFUNC(func, name, arity) \
> ++  {.fptr = { .a ## arity = func }, name, arity}
> ++
> + #define LIBM_DD(name) \
> +-  {f_ ## name, #name, 1},
> ++  CFUNC(f_ ## name, #name, 1),
> + #define LIBM_DD_NO(name) LIBM_DD(name)
> + #define LIBM_DA(name, type) LIBM_DD(name)
> + #define LIBM_DA_NO(name, type) LIBM_DD(name)
> +
> + #define LIBM_DDD(name) \
> +-  {f_ ## name, #name, 3},
> ++  CFUNC(f_ ## name, #name, 3),
> + #define LIBM_DDD_NO(name) LIBM_DDD(name)
> +
> + #define LIBM_DDDD(name) \
> +-  {f_ ## name, #name, 4},
> ++  CFUNC(f_ ## name, #name, 4),
> + #define LIBM_DDDD_NO(name) LIBM_DDDD(name)
> +
> + static const struct cfunction function_list[] = {
> + #include "libm.h"
> +-  {f_negate, "_negate", 1},
> +-#define BINOP(name) {f_ ## name, "_" #name, 3},
> ++  CFUNC(f_negate, "_negate", 1),
> ++#define BINOP(name) CFUNC(f_ ## name, "_" #name, 3),
> + BINOPS
> + #undef BINOP
> +-  {f_dump, "tojson", 1},
> +-  {f_json_parse, "fromjson", 1},
> +-  {f_tonumber, "tonumber", 1},
> +-  {f_tostring, "tostring", 1},
> +-  {f_keys, "keys", 1},
> +-  {f_keys_unsorted, "keys_unsorted", 1},
> +-  {f_startswith, "startswith", 2},
> +-  {f_endswith, "endswith", 2},
> +-  {f_ltrimstr, "ltrimstr", 2},
> +-  {f_rtrimstr, "rtrimstr", 2},
> +-  {f_string_split, "split", 2},
> +-  {f_string_explode, "explode", 1},
> +-  {f_string_implode, "implode", 1},
> +-  {f_string_indexes, "_strindices", 2},
> +-  {f_setpath, "setpath", 3}, // FIXME typechecking
> +-  {f_getpath, "getpath", 2},
> +-  {f_delpaths, "delpaths", 2},
> +-  {f_has, "has", 2},
> +-  {f_contains, "contains", 2},
> +-  {f_length, "length", 1},
> +-  {f_utf8bytelength, "utf8bytelength", 1},
> +-  {f_type, "type", 1},
> +-  {f_isinfinite, "isinfinite", 1},
> +-  {f_isnan, "isnan", 1},
> +-  {f_isnormal, "isnormal", 1},
> +-  {f_infinite, "infinite", 1},
> +-  {f_nan, "nan", 1},
> +-  {f_sort, "sort", 1},
> +-  {f_sort_by_impl, "_sort_by_impl", 2},
> +-  {f_group_by_impl, "_group_by_impl", 2},
> +-  {f_min, "min", 1},
> +-  {f_max, "max", 1},
> +-  {f_min_by_impl, "_min_by_impl", 2},
> +-  {f_max_by_impl, "_max_by_impl", 2},
> +-  {f_error, "error", 1},
> +-  {f_format, "format", 2},
> +-  {f_env, "env", 1},
> +-  {f_halt, "halt", 1},
> +-  {f_halt_error, "halt_error", 2},
> +-  {f_get_search_list, "get_search_list", 1},
> +-  {f_get_prog_origin, "get_prog_origin", 1},
> +-  {f_get_jq_origin, "get_jq_origin", 1},
> +-  {f_match, "_match_impl", 4},
> +-  {f_modulemeta, "modulemeta", 1},
> +-  {f_input, "input", 1},
> +-  {f_debug, "debug", 1},
> +-  {f_stderr, "stderr", 1},
> +-  {f_strptime, "strptime", 2},
> +-  {f_strftime, "strftime", 2},
> +-  {f_strflocaltime, "strflocaltime", 2},
> +-  {f_mktime, "mktime", 1},
> +-  {f_gmtime, "gmtime", 1},
> +-  {f_localtime, "localtime", 1},
> +-  {f_now, "now", 1},
> +-  {f_current_filename, "input_filename", 1},
> +-  {f_current_line, "input_line_number", 1},
> ++  CFUNC(f_dump, "tojson", 1),
> ++  CFUNC(f_json_parse, "fromjson", 1),
> ++  CFUNC(f_tonumber, "tonumber", 1),
> ++  CFUNC(f_tostring, "tostring", 1),
> ++  CFUNC(f_keys, "keys", 1),
> ++  CFUNC(f_keys_unsorted, "keys_unsorted", 1),
> ++  CFUNC(f_startswith, "startswith", 2),
> ++  CFUNC(f_endswith, "endswith", 2),
> ++  CFUNC(f_string_split, "split", 2),
> ++  CFUNC(f_string_explode, "explode", 1),
> ++  CFUNC(f_string_implode, "implode", 1),
> ++  CFUNC(f_string_indexes, "_strindices", 2),
> ++  CFUNC(f_setpath, "setpath", 3),
> ++  CFUNC(f_getpath, "getpath", 2),
> ++  CFUNC(f_delpaths, "delpaths", 2),
> ++  CFUNC(f_has, "has", 2),
> ++  CFUNC(f_contains, "contains", 2),
> ++  CFUNC(f_length, "length", 1),
> ++  CFUNC(f_utf8bytelength, "utf8bytelength", 1),
> ++  CFUNC(f_type, "type", 1),
> ++  CFUNC(f_isinfinite, "isinfinite", 1),
> ++  CFUNC(f_isnan, "isnan", 1),
> ++  CFUNC(f_isnormal, "isnormal", 1),
> ++  CFUNC(f_infinite, "infinite", 1),
> ++  CFUNC(f_nan, "nan", 1),
> ++  CFUNC(f_sort, "sort", 1),
> ++  CFUNC(f_sort_by_impl, "_sort_by_impl", 2),
> ++  CFUNC(f_group_by_impl, "_group_by_impl", 2),
> ++  CFUNC(f_min, "min", 1),
> ++  CFUNC(f_max, "max", 1),
> ++  CFUNC(f_min_by_impl, "_min_by_impl", 2),
> ++  CFUNC(f_max_by_impl, "_max_by_impl", 2),
> ++  CFUNC(f_error, "error", 1),
> ++  CFUNC(f_format, "format", 2),
> ++  CFUNC(f_env, "env", 1),
> ++  CFUNC(f_halt, "halt", 1),
> ++  CFUNC(f_halt_error, "halt_error", 2),
> ++  CFUNC(f_get_search_list, "get_search_list", 1),
> ++  CFUNC(f_get_prog_origin, "get_prog_origin", 1),
> ++  CFUNC(f_get_jq_origin, "get_jq_origin", 1),
> ++  CFUNC(f_match, "_match_impl", 4),
> ++  CFUNC(f_modulemeta, "modulemeta", 1),
> ++  CFUNC(f_input, "input", 1),
> ++  CFUNC(f_debug, "debug", 1),
> ++  CFUNC(f_stderr, "stderr", 1),
> ++  CFUNC(f_strptime, "strptime", 2),
> ++  CFUNC(f_strftime, "strftime", 2),
> ++  CFUNC(f_strflocaltime, "strflocaltime", 2),
> ++  CFUNC(f_mktime, "mktime", 1),
> ++  CFUNC(f_gmtime, "gmtime", 1),
> ++  CFUNC(f_localtime, "localtime", 1),
> ++  CFUNC(f_now, "now", 1),
> ++  CFUNC(f_current_filename, "input_filename", 1),
> ++  CFUNC(f_current_line, "input_line_number", 1),
> + };
> + #undef LIBM_DDDD_NO
> + #undef LIBM_DDD_NO
> +diff --git a/src/bytecode.h b/src/bytecode.h
> +index 1501985..a4055f5 100644
> +--- a/src/bytecode.h
> ++++ b/src/bytecode.h
> +@@ -2,7 +2,7 @@
> + #define BYTECODE_H
> + #include <stdint.h>
> +
> +-#include "jv.h"
> ++#include "jq.h"
> +
> + typedef enum {
> + #define OP(name, imm, in, out) name,
> +@@ -44,9 +44,14 @@ struct opcode_description {
> + const struct opcode_description* opcode_describe(opcode op);
> +
> +
> +-#define MAX_CFUNCTION_ARGS 10
> ++#define MAX_CFUNCTION_ARGS 4
> + struct cfunction {
> +-  jv (*fptr)();
> ++  union {
> ++    jv (*a1)(jq_state *, jv);
> ++    jv (*a2)(jq_state *, jv, jv);
> ++    jv (*a3)(jq_state *, jv, jv, jv);
> ++    jv (*a4)(jq_state *, jv, jv, jv, jv);
> ++  } fptr;
> +   const char* name;
> +   int nargs;
> + };
> +diff --git a/src/execute.c b/src/execute.c
> +index 9ef8368..62404db 100644
> +--- a/src/execute.c
> ++++ b/src/execute.c
> +@@ -913,14 +913,13 @@ jv jq_next(jq_state *jq) {
> +       }
> +       struct cfunction* function = &frame_current(jq)->bc->globals->cfunctions[*pc++];
> +       switch (function->nargs) {
> +-      case 1: top = ((jv (*)(jq_state *, jv))function->fptr)(jq, in[0]); break;
> +-      case 2: top = ((jv (*)(jq_state *, jv, jv))function->fptr)(jq, in[0], in[1]); break;
> +-      case 3: top = ((jv (*)(jq_state *, jv, jv, jv))function->fptr)(jq, in[0], in[1], in[2]); break;
> +-      case 4: top = ((jv (*)(jq_state *, jv, jv, jv, jv))function->fptr)(jq, in[0], in[1], in[2], in[3]); break;
> +-      case 5: top = ((jv (*)(jq_state *, jv, jv, jv, jv, jv))function->fptr)(jq, in[0], in[1], in[2], in[3], in[4]); break;
> ++      case 1: top = function->fptr.a1(jq, in[0]); break;
> ++      case 2: top = function->fptr.a2(jq, in[0], in[1]); break;
> ++      case 3: top = function->fptr.a3(jq, in[0], in[1], in[2]); break;
> ++      case 4: top = function->fptr.a4(jq, in[0], in[1], in[2], in[3]); break;
> +       // FIXME: a) up to 7 arguments (input + 6), b) should assert
> +       // because the compiler should not generate this error.
> +       default: return jv_invalid_with_msg(jv_string("Function takes too many arguments"));
> +       }
> +
> +       if (jv_is_valid(top)) {
> diff --git a/meta-oe/recipes-devtools/jq/jq_1.7.1.bb b/meta-oe/recipes-devtools/jq/jq_1.7.1.bb
> index 6b12335513..3f57adb910 100644
> --- a/meta-oe/recipes-devtools/jq/jq_1.7.1.bb
> +++ b/meta-oe/recipes-devtools/jq/jq_1.7.1.bb
> @@ -10,6 +10,9 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=488f4e0b04c0456337fb70d1ac1758ba"
>
>  GITHUB_BASE_URI = "https://github.com/jqlang/${BPN}/releases/"
>  SRC_URI = "${GITHUB_BASE_URI}/download/${BPN}-${PV}/${BPN}-${PV}.tar.gz \
> +    file://0001-builtin.c-fix-build-with-Woverlength-strings.patch \
> +    file://0002-libm.h-builtin.c-add-and-use-LIBM_DA-and-LIBM_DA_NO-.patch \
> +    file://0003-builtin.c-typecheck-builtin-cfunctions-in-function_l.patch \
>      file://run-ptest \
>      "
>  SRC_URI[sha256sum] = "478c9ca129fd2e3443fe27314b455e211e0d8c60bc8ff7df703873deeee580c2"
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#116278): https://lists.openembedded.org/g/openembedded-devel/message/116278
> Mute This Topic: https://lists.openembedded.org/mt/111897184/1997914
> Group Owner: openembedded-devel+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-devel/unsub [raj.khem@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
diff mbox series

Patch

diff --git a/meta-oe/recipes-devtools/jq/jq/0001-builtin.c-fix-build-with-Woverlength-strings.patch b/meta-oe/recipes-devtools/jq/jq/0001-builtin.c-fix-build-with-Woverlength-strings.patch
new file mode 100644
index 0000000000..cd7cdba00c
--- /dev/null
+++ b/meta-oe/recipes-devtools/jq/jq/0001-builtin.c-fix-build-with-Woverlength-strings.patch
@@ -0,0 +1,215 @@ 
+From 8707f8764dfc470d1974eb1d613f5a4bec3610ac Mon Sep 17 00:00:00 2001
+From: Emanuele Torre <torreemanuele6@gmail.com>
+Date: Fri, 26 Jan 2024 04:42:11 +0100
+Subject: [PATCH] builtin.c: fix build with -Woverlength-strings
+
+C99 only allows string literals long at most 4095 characters.
+jq_builtins was a lot longer than that.
+
+I rewrote all the optional libm error stubs in C so the value of
+jq_builtins is not build dependent.
+
+I replaced the command that generates builtin.inc with a POSIX compliant
+od|sed command that encodes builtin.jq as a comma delimited list of
+octal numbers (that can be embedded in C using a {} literal).
+
+I also added -Woverlength-strings to AM_CFLAGS to verify that the
+problem is fixed.
+
+Fixes #1481
+Upstream-Status: Backport [605836b builtin.c: fix build with -Woverlength-strings]
+Signed-off-by: Martin Jansa <martin.jansa@gmail.com>
+---
+
+ Makefile.am   | 10 ++++--
+ src/builtin.c | 86 ++++++++++++++++++++++++---------------------------
+ 2 files changed, 48 insertions(+), 48 deletions(-)
+
+diff --git a/Makefile.am b/Makefile.am
+index 76e35df..f1f9f2e 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -19,7 +19,8 @@ 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 -Wno-unused-parameter -Wno-unused-function \
++            -Woverlength-strings
+ 
+ if WIN32
+ AM_CFLAGS += -municode
+@@ -119,7 +120,12 @@ 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 > $@
++	$(AM_V_GEN) od -v -A n -t o1 -- $< | \
++	sed -e 's/$$/ /' \
++	    -e 's/\([0123456789]\) /\1, /g' \
++	    -e 's/ $$//' \
++	    -e 's/ 0/  0/g' \
++	    -e 's/ \([123456789]\)/ 0\1/g' > $@
+ src/builtin.o: src/builtin.inc
+ 
+ CLEANFILES = src/version.h .remake-version-h src/builtin.inc src/config_opts.inc
+diff --git a/src/builtin.c b/src/builtin.c
+index 902490d..a3ce7e4 100644
+--- a/src/builtin.c
++++ b/src/builtin.c
+@@ -155,7 +155,11 @@ static jv f_ ## name(jq_state *jq, jv input) { \
+   jv_free(input); \
+   return ret; \
+ }
+-#define LIBM_DD_NO(name)
++#define LIBM_DD_NO(name) \
++static jv f_ ## name(jq_state *jq, jv input) { \
++  jv error = jv_string("Error: " #name "/0 not found at build time"); \
++  return ret_error(input, error); \
++}
+ 
+ #define LIBM_DDD(name) \
+ static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
+@@ -173,7 +177,12 @@ static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
+   jv_free(b); \
+   return ret; \
+ }
+-#define LIBM_DDD_NO(name)
++#define LIBM_DDD_NO(name) \
++static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
++  jv_free(b); \
++  jv error = jv_string("Error: " #name "/2 not found at build time"); \
++  return ret_error2(input, a, error); \
++}
+ 
+ #define LIBM_DDDD(name) \
+ static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
+@@ -199,7 +208,14 @@ static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
+   jv_free(c); \
+   return ret; \
+ }
+-#define LIBM_DDDD_NO(name)
++#define LIBM_DDDD_NO(name) \
++static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
++  jv_free(c) \
++  jv_free(b); \
++  jv error = jv_string("Error: " #name "/3 not found at build time"); \
++  return ret_error2(input, a, error); \
++}
++
+ #include "libm.h"
+ #undef LIBM_DDDD_NO
+ #undef LIBM_DDD_NO
+@@ -226,6 +242,11 @@ static jv f_frexp(jq_state *jq, jv input) {
+   jv_free(input);
+   return ret;
+ }
++#else
++static jv f_frexp(jq_state *jq, jv input) {
++  jv error = jv_string("Error: frexp/0 not found at build time");
++  return ret_error(input, error);
++}
+ #endif
+ #ifdef HAVE_MODF
+ static jv f_modf(jq_state *jq, jv input) {
+@@ -237,6 +258,11 @@ static jv f_modf(jq_state *jq, jv input) {
+   jv_free(input);
+   return jv_array_append(ret, jv_number(i));
+ }
++#else
++static jv f_modf(jq_state *jq, jv input) {
++  jv error = jv_string("Error: modf/0 not found at build time");
++  return ret_error(input, error);
++}
+ #endif
+ #ifdef HAVE_LGAMMA_R
+ static jv f_lgamma_r(jq_state *jq, jv input) {
+@@ -248,6 +274,11 @@ static jv f_lgamma_r(jq_state *jq, jv input) {
+   jv_free(input);
+   return jv_array_append(ret, jv_number(sign));
+ }
++#else
++static jv f_lgamma_r(jq_state *jq, jv input) {
++  jv error = jv_string("Error: lgamma_r/0 not found at build time");
++  return ret_error(input, error);
++}
+ #endif
+ 
+ static jv f_negate(jq_state *jq, jv input) {
+@@ -1703,27 +1734,21 @@ static jv f_current_line(jq_state *jq, jv a) {
+ 
+ #define LIBM_DD(name) \
+   {f_ ## name,  #name, 1},
+-#define LIBM_DD_NO(name)
++#define LIBM_DD_NO(name) LIBM_DD(name)
+ 
+ #define LIBM_DDD(name) \
+   {f_ ## name, #name, 3},
+-#define LIBM_DDD_NO(name)
++#define LIBM_DDD_NO(name) LIBM_DDD(name)
+ 
+ #define LIBM_DDDD(name) \
+   {f_ ## name, #name, 4},
+-#define LIBM_DDDD_NO(name)
++#define LIBM_DDDD_NO(name) LIBM_DDDD(name)
+ 
+ static const struct cfunction function_list[] = {
+ #include "libm.h"
+-#ifdef HAVE_FREXP
+   {f_frexp,"frexp", 1},
+-#endif
+-#ifdef HAVE_MODF
+   {f_modf,"modf", 1},
+-#endif
+-#ifdef HAVE_LGAMMA_R
+   {f_lgamma_r,"lgamma_r", 1},
+-#endif
+   {f_negate, "_negate", 1},
+ #define BINOP(name) {f_ ## name, "_" #name, 3},
+ BINOPS
+@@ -1838,42 +1863,11 @@ static block bind_bytecoded_builtins(block b) {
+   return BLOCK(builtins, b);
+ }
+ 
+-static const char jq_builtins[] =
++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
+-
+-#ifdef __APPLE__
+-#undef HAVE_GAMMA
+-#undef HAVE_EXP10
+-#undef HAVE_DREM
+-#undef HAVE_SIGNIFICAND
+-#endif
++  '\0',
++};
+ 
+ static block gen_builtin_list(block builtins) {
+   jv list = jv_array_append(block_list_funcs(builtins, 1), jv_string("builtins/0"));
diff --git a/meta-oe/recipes-devtools/jq/jq/0002-libm.h-builtin.c-add-and-use-LIBM_DA-and-LIBM_DA_NO-.patch b/meta-oe/recipes-devtools/jq/jq/0002-libm.h-builtin.c-add-and-use-LIBM_DA-and-LIBM_DA_NO-.patch
new file mode 100644
index 0000000000..68b8cb4f6e
--- /dev/null
+++ b/meta-oe/recipes-devtools/jq/jq/0002-libm.h-builtin.c-add-and-use-LIBM_DA-and-LIBM_DA_NO-.patch
@@ -0,0 +1,164 @@ 
+From c65e6fa48e6da30727c87ccdd88d8fb6a7a70f20 Mon Sep 17 00:00:00 2001
+From: Emanuele Torre <torreemanuele6@gmail.com>
+Date: Fri, 26 Jan 2024 11:26:57 +0100
+Subject: [PATCH] libm.h+builtin.c: add and use LIBM_DA and LIBM_DA_NO macros
+
+For functions that from one double return an array with two numbers.
+Upstream-Status: Backport [bd3c828 libm.h+builtin.c: add and use LIBM_DA and LIBM_DA_NO macros]
+Signed-off-by: Martin Jansa <martin.jansa@gmail.com>
+---
+ src/builtin.c | 78 ++++++++++++++++-----------------------------------
+ src/libm.h    | 15 ++++++++++
+ 2 files changed, 39 insertions(+), 54 deletions(-)
+
+diff --git a/src/builtin.c b/src/builtin.c
+index a3ce7e4..9b71bca 100644
+--- a/src/builtin.c
++++ b/src/builtin.c
+@@ -216,13 +216,32 @@ static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
+   return ret_error2(input, a, error); \
+ }
+ 
++#define LIBM_DA(name, type) \
++static jv f_ ## name(jq_state *jq, jv input) { \
++  if (jv_get_kind(input) != JV_KIND_NUMBER) { \
++    return type_error(input, "number required"); \
++  } \
++  type value; \
++  double d = name(jv_number_value(input), &value); \
++  jv ret = JV_ARRAY(jv_number(d), jv_number(value)); \
++  jv_free(input); \
++  return ret; \
++}
++#define LIBM_DA_NO(name, type) \
++static jv f_ ## name(jq_state *jq, jv input) { \
++  jv error = jv_string("Error: " #name "/0 not found at build time"); \
++  return ret_error(input, error); \
++}
++
+ #include "libm.h"
+ #undef LIBM_DDDD_NO
+ #undef LIBM_DDD_NO
+ #undef LIBM_DD_NO
++#undef LIBM_DA_NO
+ #undef LIBM_DDDD
+ #undef LIBM_DDD
+ #undef LIBM_DD
++#undef LIBM_DA
+ 
+ #ifdef __APPLE__
+ #undef gamma
+@@ -231,56 +250,6 @@ static jv f_ ## name(jq_state *jq, jv input, jv a, jv b, jv c) { \
+ #undef exp10
+ #endif
+ 
+-#ifdef HAVE_FREXP
+-static jv f_frexp(jq_state *jq, jv input) {
+-  if (jv_get_kind(input) != JV_KIND_NUMBER) {
+-    return type_error(input, "number required");
+-  }
+-  int exp;
+-  double d = frexp(jv_number_value(input), &exp);
+-  jv ret = JV_ARRAY(jv_number(d), jv_number(exp));
+-  jv_free(input);
+-  return ret;
+-}
+-#else
+-static jv f_frexp(jq_state *jq, jv input) {
+-  jv error = jv_string("Error: frexp/0 not found at build time");
+-  return ret_error(input, error);
+-}
+-#endif
+-#ifdef HAVE_MODF
+-static jv f_modf(jq_state *jq, jv input) {
+-  if (jv_get_kind(input) != JV_KIND_NUMBER) {
+-    return type_error(input, "number required");
+-  }
+-  double i;
+-  jv ret = JV_ARRAY(jv_number(modf(jv_number_value(input), &i)));
+-  jv_free(input);
+-  return jv_array_append(ret, jv_number(i));
+-}
+-#else
+-static jv f_modf(jq_state *jq, jv input) {
+-  jv error = jv_string("Error: modf/0 not found at build time");
+-  return ret_error(input, error);
+-}
+-#endif
+-#ifdef HAVE_LGAMMA_R
+-static jv f_lgamma_r(jq_state *jq, jv input) {
+-  if (jv_get_kind(input) != JV_KIND_NUMBER) {
+-    return type_error(input, "number required");
+-  }
+-  int sign;
+-  jv ret = JV_ARRAY(jv_number(lgamma_r(jv_number_value(input), &sign)));
+-  jv_free(input);
+-  return jv_array_append(ret, jv_number(sign));
+-}
+-#else
+-static jv f_lgamma_r(jq_state *jq, jv input) {
+-  jv error = jv_string("Error: lgamma_r/0 not found at build time");
+-  return ret_error(input, error);
+-}
+-#endif
+-
+ static jv f_negate(jq_state *jq, jv input) {
+   if (jv_get_kind(input) != JV_KIND_NUMBER) {
+     return type_error(input, "cannot be negated");
+@@ -1733,8 +1702,10 @@ static jv f_current_line(jq_state *jq, jv a) {
+ }
+ 
+ #define LIBM_DD(name) \
+-  {f_ ## name,  #name, 1},
++  {f_ ## name, #name, 1},
+ #define LIBM_DD_NO(name) LIBM_DD(name)
++#define LIBM_DA(name, type) LIBM_DD(name)
++#define LIBM_DA_NO(name, type) LIBM_DD(name)
+ 
+ #define LIBM_DDD(name) \
+   {f_ ## name, #name, 3},
+@@ -1746,9 +1717,6 @@ static jv f_current_line(jq_state *jq, jv a) {
+ 
+ static const struct cfunction function_list[] = {
+ #include "libm.h"
+-  {f_frexp,"frexp", 1},
+-  {f_modf,"modf", 1},
+-  {f_lgamma_r,"lgamma_r", 1},
+   {f_negate, "_negate", 1},
+ #define BINOP(name) {f_ ## name, "_" #name, 3},
+ BINOPS
+@@ -1813,9 +1781,11 @@ BINOPS
+ #undef LIBM_DDDD_NO
+ #undef LIBM_DDD_NO
+ #undef LIBM_DD_NO
++#undef LIBM_DA_NO
+ #undef LIBM_DDDD
+ #undef LIBM_DDD
+ #undef LIBM_DD
++#undef LIBM_DA
+ 
+ struct bytecoded_builtin { const char* name; block code; };
+ static block bind_bytecoded_builtins(block b) {
+diff --git a/src/libm.h b/src/libm.h
+index 8efc1c5..7332bd8 100644
+--- a/src/libm.h
++++ b/src/libm.h
+@@ -289,3 +289,18 @@ LIBM_DDD(ldexp)
+ #else
+ LIBM_DDD_NO(ldexp)
+ #endif
++#ifdef HAVE_MODF
++LIBM_DA(modf, double)
++#else
++LIBM_DA_NO(modf, double)
++#endif
++#ifdef HAVE_FREXP
++LIBM_DA(frexp, int)
++#else
++LIBM_DA_NO(frexp, int)
++#endif
++#ifdef HAVE_LGAMMA_R
++LIBM_DA(lgamma_r, int)
++#else
++LIBM_DA_NO(lgamma_r, int)
++#endif
diff --git a/meta-oe/recipes-devtools/jq/jq/0003-builtin.c-typecheck-builtin-cfunctions-in-function_l.patch b/meta-oe/recipes-devtools/jq/jq/0003-builtin.c-typecheck-builtin-cfunctions-in-function_l.patch
new file mode 100644
index 0000000000..f8b6c5baf6
--- /dev/null
+++ b/meta-oe/recipes-devtools/jq/jq/0003-builtin.c-typecheck-builtin-cfunctions-in-function_l.patch
@@ -0,0 +1,249 @@ 
+From 98839759a92e3ad41870bfc7415f0ecf320b5097 Mon Sep 17 00:00:00 2001
+From: Emanuele Torre <torreemanuele6@gmail.com>
+Date: Mon, 25 Nov 2024 07:47:14 +0100
+Subject: [PATCH] builtin.c: typecheck builtin cfunctions in function_list
+
+In C23 (default C standard used by GCC 15),  jv (*fptr)();  has become
+equivalent to  jv (*fptr)(void);  so we can no longer assign builtin
+implemenations directly to the fptr member of cfunctions without
+generating a compile error.
+
+Since there does not seem to be any straight-forward way to tell
+autoconf to force the compiler to use C99 short of explicitly adding
+-std=c99 to CFLAGS, it is probably a cleaner solution to just make the
+code C23 compatible.
+
+A possible solution could have been to just redeclare  cfunction.fptr
+as void*, but then the functions' return type would not have been type
+checked (e.g. if you tried to add a {printf, "printf", 2}, where printf
+is a function that does not return jv, the compiler wouldn't have
+complained.)
+We were already not typechecking the arguments of the functions, so e.g.
+  {binop_plus, "_plus", 3},  /* instead of {f_plus, "_plus, 3},       */
+  {f_setpath, "setpath", 4}, /* instead of {f_setpath, "setpath", 3}, */
+compile without errors despite not having the correct prototype.
+
+So I thought of instead improving the situation by redefining
+cfunction.fptr as a union of function pointers with the prototypes that
+the jq bytecode interpreter can call, and use a macro to add the builtin
+functions to function_list using to the arity argument to assign the
+implementation function to the appropriate union member.
+
+Now the code won't compile if the wrong arity, or an arity not supported
+by the bytecode interpreter (>5 = 1input+4arguments), or a prototype not
+jallable by the bytecode interpreter (e.g. binop_plus that doesn't
+expect a  jq_state*  argument).
+
+Also, the code now compiles with gcc -std=c23.
+
+Fixes #3206
+Upstream-Status: Backport [0b82b38 builtin.c: typecheck builtin cfunctions in function_list]
+Signed-off-by: Martin Jansa <martin.jansa@gmail.com>
+---
+ src/builtin.c  | 126 +++++++++++++++++++++++++------------------------
+ src/bytecode.h |  11 +++--
+ src/execute.c  |  11 ++---
+ 3 files changed, 78 insertions(+), 70 deletions(-)
+
+diff --git a/src/builtin.c b/src/builtin.c
+index 9b71bca..6ba6511 100644
+--- a/src/builtin.c
++++ b/src/builtin.c
+@@ -1701,82 +1701,83 @@ static jv f_current_line(jq_state *jq, jv a) {
+   return jq_util_input_get_current_line(jq);
+ }
+ 
++#define CFUNC(func, name, arity) \
++  {.fptr = { .a ## arity = func }, name, arity}
++
+ #define LIBM_DD(name) \
+-  {f_ ## name, #name, 1},
++  CFUNC(f_ ## name, #name, 1),
+ #define LIBM_DD_NO(name) LIBM_DD(name)
+ #define LIBM_DA(name, type) LIBM_DD(name)
+ #define LIBM_DA_NO(name, type) LIBM_DD(name)
+ 
+ #define LIBM_DDD(name) \
+-  {f_ ## name, #name, 3},
++  CFUNC(f_ ## name, #name, 3),
+ #define LIBM_DDD_NO(name) LIBM_DDD(name)
+ 
+ #define LIBM_DDDD(name) \
+-  {f_ ## name, #name, 4},
++  CFUNC(f_ ## name, #name, 4),
+ #define LIBM_DDDD_NO(name) LIBM_DDDD(name)
+ 
+ static const struct cfunction function_list[] = {
+ #include "libm.h"
+-  {f_negate, "_negate", 1},
+-#define BINOP(name) {f_ ## name, "_" #name, 3},
++  CFUNC(f_negate, "_negate", 1),
++#define BINOP(name) CFUNC(f_ ## name, "_" #name, 3),
+ BINOPS
+ #undef BINOP
+-  {f_dump, "tojson", 1},
+-  {f_json_parse, "fromjson", 1},
+-  {f_tonumber, "tonumber", 1},
+-  {f_tostring, "tostring", 1},
+-  {f_keys, "keys", 1},
+-  {f_keys_unsorted, "keys_unsorted", 1},
+-  {f_startswith, "startswith", 2},
+-  {f_endswith, "endswith", 2},
+-  {f_ltrimstr, "ltrimstr", 2},
+-  {f_rtrimstr, "rtrimstr", 2},
+-  {f_string_split, "split", 2},
+-  {f_string_explode, "explode", 1},
+-  {f_string_implode, "implode", 1},
+-  {f_string_indexes, "_strindices", 2},
+-  {f_setpath, "setpath", 3}, // FIXME typechecking
+-  {f_getpath, "getpath", 2},
+-  {f_delpaths, "delpaths", 2},
+-  {f_has, "has", 2},
+-  {f_contains, "contains", 2},
+-  {f_length, "length", 1},
+-  {f_utf8bytelength, "utf8bytelength", 1},
+-  {f_type, "type", 1},
+-  {f_isinfinite, "isinfinite", 1},
+-  {f_isnan, "isnan", 1},
+-  {f_isnormal, "isnormal", 1},
+-  {f_infinite, "infinite", 1},
+-  {f_nan, "nan", 1},
+-  {f_sort, "sort", 1},
+-  {f_sort_by_impl, "_sort_by_impl", 2},
+-  {f_group_by_impl, "_group_by_impl", 2},
+-  {f_min, "min", 1},
+-  {f_max, "max", 1},
+-  {f_min_by_impl, "_min_by_impl", 2},
+-  {f_max_by_impl, "_max_by_impl", 2},
+-  {f_error, "error", 1},
+-  {f_format, "format", 2},
+-  {f_env, "env", 1},
+-  {f_halt, "halt", 1},
+-  {f_halt_error, "halt_error", 2},
+-  {f_get_search_list, "get_search_list", 1},
+-  {f_get_prog_origin, "get_prog_origin", 1},
+-  {f_get_jq_origin, "get_jq_origin", 1},
+-  {f_match, "_match_impl", 4},
+-  {f_modulemeta, "modulemeta", 1},
+-  {f_input, "input", 1},
+-  {f_debug, "debug", 1},
+-  {f_stderr, "stderr", 1},
+-  {f_strptime, "strptime", 2},
+-  {f_strftime, "strftime", 2},
+-  {f_strflocaltime, "strflocaltime", 2},
+-  {f_mktime, "mktime", 1},
+-  {f_gmtime, "gmtime", 1},
+-  {f_localtime, "localtime", 1},
+-  {f_now, "now", 1},
+-  {f_current_filename, "input_filename", 1},
+-  {f_current_line, "input_line_number", 1},
++  CFUNC(f_dump, "tojson", 1),
++  CFUNC(f_json_parse, "fromjson", 1),
++  CFUNC(f_tonumber, "tonumber", 1),
++  CFUNC(f_tostring, "tostring", 1),
++  CFUNC(f_keys, "keys", 1),
++  CFUNC(f_keys_unsorted, "keys_unsorted", 1),
++  CFUNC(f_startswith, "startswith", 2),
++  CFUNC(f_endswith, "endswith", 2),
++  CFUNC(f_string_split, "split", 2),
++  CFUNC(f_string_explode, "explode", 1),
++  CFUNC(f_string_implode, "implode", 1),
++  CFUNC(f_string_indexes, "_strindices", 2),
++  CFUNC(f_setpath, "setpath", 3),
++  CFUNC(f_getpath, "getpath", 2),
++  CFUNC(f_delpaths, "delpaths", 2),
++  CFUNC(f_has, "has", 2),
++  CFUNC(f_contains, "contains", 2),
++  CFUNC(f_length, "length", 1),
++  CFUNC(f_utf8bytelength, "utf8bytelength", 1),
++  CFUNC(f_type, "type", 1),
++  CFUNC(f_isinfinite, "isinfinite", 1),
++  CFUNC(f_isnan, "isnan", 1),
++  CFUNC(f_isnormal, "isnormal", 1),
++  CFUNC(f_infinite, "infinite", 1),
++  CFUNC(f_nan, "nan", 1),
++  CFUNC(f_sort, "sort", 1),
++  CFUNC(f_sort_by_impl, "_sort_by_impl", 2),
++  CFUNC(f_group_by_impl, "_group_by_impl", 2),
++  CFUNC(f_min, "min", 1),
++  CFUNC(f_max, "max", 1),
++  CFUNC(f_min_by_impl, "_min_by_impl", 2),
++  CFUNC(f_max_by_impl, "_max_by_impl", 2),
++  CFUNC(f_error, "error", 1),
++  CFUNC(f_format, "format", 2),
++  CFUNC(f_env, "env", 1),
++  CFUNC(f_halt, "halt", 1),
++  CFUNC(f_halt_error, "halt_error", 2),
++  CFUNC(f_get_search_list, "get_search_list", 1),
++  CFUNC(f_get_prog_origin, "get_prog_origin", 1),
++  CFUNC(f_get_jq_origin, "get_jq_origin", 1),
++  CFUNC(f_match, "_match_impl", 4),
++  CFUNC(f_modulemeta, "modulemeta", 1),
++  CFUNC(f_input, "input", 1),
++  CFUNC(f_debug, "debug", 1),
++  CFUNC(f_stderr, "stderr", 1),
++  CFUNC(f_strptime, "strptime", 2),
++  CFUNC(f_strftime, "strftime", 2),
++  CFUNC(f_strflocaltime, "strflocaltime", 2),
++  CFUNC(f_mktime, "mktime", 1),
++  CFUNC(f_gmtime, "gmtime", 1),
++  CFUNC(f_localtime, "localtime", 1),
++  CFUNC(f_now, "now", 1),
++  CFUNC(f_current_filename, "input_filename", 1),
++  CFUNC(f_current_line, "input_line_number", 1),
+ };
+ #undef LIBM_DDDD_NO
+ #undef LIBM_DDD_NO
+diff --git a/src/bytecode.h b/src/bytecode.h
+index 1501985..a4055f5 100644
+--- a/src/bytecode.h
++++ b/src/bytecode.h
+@@ -2,7 +2,7 @@
+ #define BYTECODE_H
+ #include <stdint.h>
+ 
+-#include "jv.h"
++#include "jq.h"
+ 
+ typedef enum {
+ #define OP(name, imm, in, out) name,
+@@ -44,9 +44,14 @@ struct opcode_description {
+ const struct opcode_description* opcode_describe(opcode op);
+ 
+ 
+-#define MAX_CFUNCTION_ARGS 10
++#define MAX_CFUNCTION_ARGS 4
+ struct cfunction {
+-  jv (*fptr)();
++  union {
++    jv (*a1)(jq_state *, jv);
++    jv (*a2)(jq_state *, jv, jv);
++    jv (*a3)(jq_state *, jv, jv, jv);
++    jv (*a4)(jq_state *, jv, jv, jv, jv);
++  } fptr;
+   const char* name;
+   int nargs;
+ };
+diff --git a/src/execute.c b/src/execute.c
+index 9ef8368..62404db 100644
+--- a/src/execute.c
++++ b/src/execute.c
+@@ -913,14 +913,13 @@ jv jq_next(jq_state *jq) {
+       }
+       struct cfunction* function = &frame_current(jq)->bc->globals->cfunctions[*pc++];
+       switch (function->nargs) {
+-      case 1: top = ((jv (*)(jq_state *, jv))function->fptr)(jq, in[0]); break;
+-      case 2: top = ((jv (*)(jq_state *, jv, jv))function->fptr)(jq, in[0], in[1]); break;
+-      case 3: top = ((jv (*)(jq_state *, jv, jv, jv))function->fptr)(jq, in[0], in[1], in[2]); break;
+-      case 4: top = ((jv (*)(jq_state *, jv, jv, jv, jv))function->fptr)(jq, in[0], in[1], in[2], in[3]); break;
+-      case 5: top = ((jv (*)(jq_state *, jv, jv, jv, jv, jv))function->fptr)(jq, in[0], in[1], in[2], in[3], in[4]); break;
++      case 1: top = function->fptr.a1(jq, in[0]); break;
++      case 2: top = function->fptr.a2(jq, in[0], in[1]); break;
++      case 3: top = function->fptr.a3(jq, in[0], in[1], in[2]); break;
++      case 4: top = function->fptr.a4(jq, in[0], in[1], in[2], in[3]); break;
+       // FIXME: a) up to 7 arguments (input + 6), b) should assert
+       // because the compiler should not generate this error.
+       default: return jv_invalid_with_msg(jv_string("Function takes too many arguments"));
+       }
+ 
+       if (jv_is_valid(top)) {
diff --git a/meta-oe/recipes-devtools/jq/jq_1.7.1.bb b/meta-oe/recipes-devtools/jq/jq_1.7.1.bb
index 6b12335513..3f57adb910 100644
--- a/meta-oe/recipes-devtools/jq/jq_1.7.1.bb
+++ b/meta-oe/recipes-devtools/jq/jq_1.7.1.bb
@@ -10,6 +10,9 @@  LIC_FILES_CHKSUM = "file://COPYING;md5=488f4e0b04c0456337fb70d1ac1758ba"
 
 GITHUB_BASE_URI = "https://github.com/jqlang/${BPN}/releases/"
 SRC_URI = "${GITHUB_BASE_URI}/download/${BPN}-${PV}/${BPN}-${PV}.tar.gz \
+    file://0001-builtin.c-fix-build-with-Woverlength-strings.patch \
+    file://0002-libm.h-builtin.c-add-and-use-LIBM_DA-and-LIBM_DA_NO-.patch \
+    file://0003-builtin.c-typecheck-builtin-cfunctions-in-function_l.patch \
     file://run-ptest \
     "
 SRC_URI[sha256sum] = "478c9ca129fd2e3443fe27314b455e211e0d8c60bc8ff7df703873deeee580c2"