Skip to content

Commit

Permalink
Fix build warning - cast from pointer to integer of different size
Browse files Browse the repository at this point in the history
object->values used to be a size in pass 1 and a pointer in pass 2.

A union has been added to avoid such GCC warning:
* cast from pointer to integer of different size
* dereferencing type-punned pointer will break strict-aliasing rules

The union is visible only when JSON__PRVATE_API is defined, but this
trick relies on sizeof(json_object_entry *) >= sizeof(unsigned int).
Is that acceptable?

The name of the new union is "_p" (as in private) instead of "u",
but it could be renamed back to "u", or even "_reserved" or "_r".
  • Loading branch information
DimitriPapadopoulos committed Aug 28, 2021
1 parent 60fd8a7 commit a04c7c6
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 12 deletions.
21 changes: 11 additions & 10 deletions json.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* SUCH DAMAGE.
*/

#define JSON__PRIVATE_API
#include "json.h"

#ifdef _MSC_VER
Expand Down Expand Up @@ -151,15 +152,15 @@ static int new_value (json_state * state,
if (value->u.object.length == 0)
break;

values_size = sizeof (*value->u.object.values) * value->u.object.length;
values_size = sizeof (*value->u.object._p.values) * value->u.object.length;

if (! (value->u.object.values = (json_object_entry *) json_alloc
(state, values_size + ((unsigned long) value->u.object.values), 0)) )
if (! (value->u.object._p.values = (json_object_entry *) json_alloc
(state, values_size + value->u.object._p._reserved_length, 0)) )
{
return 0;
}

value->_reserved.object_mem = (*(char **) &value->u.object.values) + values_size;
value->_reserved.object_mem = (*(char **) &value->u.object._p.values) + values_size;

value->u.object.length = 0;
break;
Expand Down Expand Up @@ -422,13 +423,13 @@ json_value * json_parse_ex (json_settings * settings,
case json_object:

if (state.first_pass)
(*(json_char **) &top->u.object.values) += string_length + 1;
top->u.object._p._reserved_length += string_length + 1;
else
{
top->u.object.values [top->u.object.length].name
top->u.object._p.values [top->u.object.length].name
= (json_char *) top->_reserved.object_mem;

top->u.object.values [top->u.object.length].name_length
top->u.object._p.values [top->u.object.length].name_length
= string_length;

(*(json_char **) &top->_reserved.object_mem) += string_length + 1;
Expand Down Expand Up @@ -905,7 +906,7 @@ json_value * json_parse_ex (json_settings * settings,
{
case json_object:

parent->u.object.values
parent->u.object._p.values
[parent->u.object.length].value = top;

break;
Expand Down Expand Up @@ -1011,11 +1012,11 @@ void json_value_free_ex (json_settings * settings, json_value * value)

if (!value->u.object.length)
{
settings->mem_free (value->u.object.values, settings->user_data);
settings->mem_free (value->u.object._p.values, settings->user_data);
break;
}

value = value->u.object.values [-- value->u.object.length].value;
value = value->u.object._p.values [-- value->u.object.length].value;
continue;

case json_string:
Expand Down
30 changes: 28 additions & 2 deletions json.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,35 @@ typedef struct _json_value
{
unsigned int length;

#ifdef JSON__PRIVATE_API
union
{
json_object_entry * values;
unsigned int _reserved_length;

} _p;
#else
json_object_entry * values;
#endif

#if defined(__cplusplus)
json_object_entry * begin () const
{ return values;
{
#ifdef JSON__PRIVATE_API
return _p.values;
#else
return values;
#endif

}
json_object_entry * end () const
{ return values + length;
{
#ifdef JSON__PRIVATE_API
return _p.values + length;
#else
return values + length;
#endif

}
#endif

Expand Down Expand Up @@ -195,8 +216,13 @@ typedef struct _json_value
return json_value_none;

for (unsigned int i = 0; i < u.object.length; ++ i)
#ifdef JSON__PRIVATE_API
if (!strcmp (u.object._p.values [i].name, index))
return *u.object._p.values [i].value;
#else
if (!strcmp (u.object.values [i].name, index))
return *u.object.values [i].value;
#endif

return json_value_none;
}
Expand Down

0 comments on commit a04c7c6

Please sign in to comment.