Skip to content

Commit

Permalink
json: Fix handling for long integers
Browse files Browse the repository at this point in the history
This patch adds the "enable_long_quoting" modparam (default: OFF), which
causes larger integers to be returned as strings, in order to avoid the
integer overflow and data loss.

(cherry picked from commit b191025)

Author: Vlad Paiu <[email protected]>
Add support for bigints ( store as string when exposing to opensips script )

(cherry picked from commit f324a1a)

Author: Vlad Paiu <[email protected]>
Fixed undefined int_value

(cherry picked from commit ae113c7)
  • Loading branch information
liviuchircu committed Dec 10, 2024
1 parent b16e49c commit c1b2317
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 10 deletions.
25 changes: 24 additions & 1 deletion modules/json/doc/json_admin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,32 @@
<section id="exported_parameters" xreflabel="Exported Parameters">
<title>Exported Parameters</title>

<section id="param_enable_long_quoting" xreflabel="enable_long_quoting">
<title><varname>enable_long_quoting</varname> (boolean)</title>
<para>
The module does not export any parameters.
Enable this parameter if your input JSONs contain signed integers which
do not fit into 4 bytes (e.g. larger than 2147483647, etc.). If the
parameter is enabled, 4-byte integers will continue to be returned as
integers, while larger values will be returned as strings, in order to
avoid the integer overflow.
</para>
<para>
<emphasis>
Default value is <emphasis>false</emphasis>.
</emphasis>
</para>
<example>
<title>Set <varname>enable_long_quoting</varname> parameter</title>
<programlisting format="linespecific">
...
modparam("json", "enable_long_quoting", true)
...
# normalize the "gateway_id" int/string value to be always a string
$var(gateway_id) = "" + $json(body/gateway_id);
...
</programlisting>
</example>
</section>

</section>

Expand Down
33 changes: 24 additions & 9 deletions modules/json/json.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ typedef struct _json_name

pv_json_t * all;
char buff[JSON_FILE_BUF_SIZE];
int json_long_quoting;

static int mod_init(void);
static int child_init(int );
Expand Down Expand Up @@ -128,6 +129,12 @@ static const cmd_export_t cmds[]={
{0,0,{{0,0,0}},0}
};

static const param_export_t mod_params[]={
{ "enable_long_quoting", INT_PARAM, &json_long_quoting },
{ 0,0,0 }
};


static const pv_export_t mod_items[] = {
{ str_const_init("json"), PVT_JSON, pv_get_json,
pv_set_json, pv_parse_json_name, pv_parse_json_index, 0, 0},
Expand All @@ -143,15 +150,15 @@ struct module_exports exports= {
MOD_TYPE_DEFAULT,/* class of this module */
MODULE_VERSION,
DEFAULT_DLFLAGS, /* dlopen flags */
0, /* load function */
0, /* load function */
NULL, /* OpenSIPS module dependencies */
cmds, /* exported functions */
0, /* exported async functions */
0, /* param exports */
0, /* exported statistics */
0, /* exported MI functions */
mod_params, /* param exports */
0, /* exported statistics */
0, /* exported MI functions */
mod_items, /* exported pseudo-variables */
0, /* exported transformations */
0, /* exported transformations */
0, /* extra processes */
0, /* module pre-initialization function */
mod_init, /* module initialization function */
Expand Down Expand Up @@ -415,6 +422,7 @@ int pv_get_json_ext(struct sip_msg* msg, pv_param_t* pvp, pv_value_t* val, int
json_t * obj;
json_name * id = (json_name *) pvp->pvn.u.dname;
UNUSED(id);
int64_t int_value;

if( expand_tag_list( msg, ((json_name *)pvp->pvn.u.dname)->tags ) < 0)
{
Expand Down Expand Up @@ -457,10 +465,17 @@ int pv_get_json_ext(struct sip_msg* msg, pv_param_t* pvp, pv_value_t* val, int

if( json_object_is_type(obj, json_type_int) )
{
val->rs.s = sint2str(json_object_get_int(obj), &val->rs.len);
val->ri = json_object_get_int(obj);;
val->flags |= PV_VAL_INT|PV_TYPE_INT|PV_VAL_STR;

int_value = json_object_get_int64(obj);
val->rs.s = sint2str(int_value, &val->rs.len);

if (!json_long_quoting || (int_value>=INT_MIN && int_value<=INT_MAX)) {
/* safe to store it as an INT in the pvar */
val->ri = int_value;
val->flags |= PV_VAL_INT|PV_TYPE_INT|PV_VAL_STR;
} else {
/* we would overflow/underflow, store as string only */
val->flags |= PV_VAL_STR;
}
}
else if( json_object_is_type(obj, json_type_string))
{
Expand Down

0 comments on commit c1b2317

Please sign in to comment.