ACK: [PATCH] lib: fwts_json: free objects where necessary to plug heap leaks

Alex Hung alex.hung at canonical.com
Thu Apr 29 00:49:06 UTC 2021


On 2021-04-28 5:26 p.m., Colin King wrote:
> From: Colin Ian King <colin.king at canonical.com>
> 
> There are quite a few places where token handling and object
> handling error paths need to free any allocated token or json
> objects.  Fix these.
> 
> Signed-off-by: Colin Ian King <colin.king at canonical.com>
> ---
>  src/lib/src/fwts_json.c | 60 +++++++++++++++++++++++++++++++++--------
>  1 file changed, 49 insertions(+), 11 deletions(-)
> 
> diff --git a/src/lib/src/fwts_json.c b/src/lib/src/fwts_json.c
> index 3182ea74..15f2a556 100644
> --- a/src/lib/src/fwts_json.c
> +++ b/src/lib/src/fwts_json.c
> @@ -261,6 +261,18 @@ int json_get_keyword(json_file *jfile, json_token *token)
>  	return token_error;
>  }
>  
> +/*
> + *  json_free_token()
> + *	free any heap allocated members in token when required
> + */
> +void json_free_token(json_token *token)
> +{
> +	if (token->type == token_string) {
> +		free(token->u.str);
> +		token->u.str = NULL;
> +	}
> +}
> +
>  /*
>   *  json_get_token()
>   *	read next input character(s) and return a matching token
> @@ -363,10 +375,14 @@ json_object *json_parse_array(json_file *jfile)
>  		obj = json_parse_object(jfile);
>  		if (!obj) {
>  			json_parse_error_where(jfile);
> -			free(array_obj);
> +			json_object_put(array_obj);
> +			return NULL;
> +		}
> +		if (json_object_array_add(array_obj, obj) < 0) {
> +			json_object_put(array_obj);
> +			json_object_put(obj);
>  			return NULL;
>  		}
> -		json_object_array_add(array_obj, obj);
>  
>  		switch (json_get_token(jfile, &token)) {
>  		case token_rbracket:
> @@ -376,9 +392,11 @@ json_object *json_parse_array(json_file *jfile)
>  		default:
>  			if (json_unget_token(jfile, &token) != 0) {
>  				fprintf(stderr, "json_parser: failed to unget a token\n");
> -				free(array_obj);
> +				json_object_put(array_obj);
> +				json_free_token(&token);
>  				return NULL;
>  			}
> +			json_free_token(&token);
>  			break;
>  		}
>  	}
> @@ -393,10 +411,10 @@ json_object *json_parse_object(json_file *jfile)
>  {
>  	json_token token;
>  	json_object *obj, *val_obj;
> -	char *key = NULL;
>  
>  	if (json_get_token(jfile, &token) != token_lbrace) {
>  		fprintf(stderr, "json_parser: expecting '{', got %s instead\n", json_token_string(&token));
> +		json_free_token(&token);
>  		return NULL;
>  	}
>  
> @@ -405,59 +423,76 @@ json_object *json_parse_object(json_file *jfile)
>  		goto err_nomem;
>  
>  	for (;;) {
> +		char *key = NULL;
> +
>  		switch (json_get_token(jfile, &token)) {
>  		case token_rbrace:
> +			json_free_token(&token);
>  			return obj;
>  		case token_string:
> -			key = token.u.str;
> +			key = strdup(token.u.str);
>  			if (!key)
>  				goto err_nomem;
> -			token.u.str = NULL;
> +			json_free_token(&token);
>  			break;
>  		default:
>  			fprintf(stderr, "json_parser: expecting } or key literal string, got %s instead\n", json_token_string(&token));
>  			goto err_free;
>  		}
> +
> +		json_free_token(&token);
>  		if (json_get_token(jfile, &token) != token_colon) {
>  			fprintf(stderr, "json_parser: expecting ':', got %s instead\n", json_token_string(&token));
> +			free(key);
>  			goto err_free;
>  		}
>  		switch (json_get_token(jfile, &token)) {
>  		case token_string:
>  			val_obj = json_object_new_string(token.u.str);
> -			if (!val_obj)
> +			if (!val_obj) {
> +				free(key);
>  				goto err_nomem;
> +			}
>  			json_object_object_add(obj, key, val_obj);
> -			free(key);
>  			break;
>  		case token_int:
>  			val_obj = json_object_new_int(token.u.intval);
> -			if (!val_obj)
> +			if (!val_obj) {
> +				free(key);
>  				goto err_nomem;
> +			}
>  			json_object_object_add(obj, key, val_obj);
> -			free(key);
>  			break;
>  		case token_lbracket:
>  			val_obj = json_parse_array(jfile);
> -			if (!val_obj)
> +			if (!val_obj) {
> +				free(key);
>  				goto err_nomem;
> +			}
>  			json_object_object_add(obj, key, val_obj);
>  			break;
>  		case token_lbrace:
>  			fprintf(stderr, "json_parser: nested objects not supported\n");
> +			free(key);
>  			goto err_free;
>  		case token_true:
>  		case token_false:
>  		case token_null:
>  			fprintf(stderr, "json_parser: tokens %s not supported\n", json_token_string(&token));
> +			free(key);
>  			goto err_free;
>  		default:
>  			fprintf(stderr, "json_parser: unexpected token %s\n", json_token_string(&token));
>  		}
> +		free(key);
> +
> +		json_free_token(&token);
>  		switch (json_get_token(jfile, &token)) {
>  		case token_comma:
> +			json_free_token(&token);
>  			continue;
>  		case token_rbrace:
> +			json_free_token(&token);
>  			return obj;
>  		default:
>  			fprintf(stderr, "json_parser: expected , or }, got %s instead\n", json_token_string(&token));
> @@ -470,6 +505,7 @@ err_nomem:
>  	json_parse_error_where(jfile);
>  err_free:
>  	free(obj);
> +	json_free_token(&token);
>  	return NULL;
>  }
>  
> @@ -880,6 +916,7 @@ static char *json_object_to_json_string_indent(json_object *obj, int indent)
>  					return NULL;
>  				}
>  				str = str_append(str, obj_str);
> +				free(obj_str);
>  				if (!str)
>  					return NULL;
>  			}
> @@ -919,6 +956,7 @@ static char *json_object_to_json_string_indent(json_object *obj, int indent)
>  					return NULL;
>  				}
>  				str = str_append(str, obj_str);
> +				free(obj_str);
>  				if (!str)
>  					return NULL;
>  			}
> 


Acked-by: Alex Hung <alex.hung at canonical.com>



More information about the fwts-devel mailing list