Browse Source

H2O: Fix a use of deallocated memory (#4535)

Anton Kirilov 6 years ago
parent
commit
bbdb9b444c
1 changed files with 31 additions and 25 deletions
  1. 31 25
      frameworks/C/h2o/src/world.c

+ 31 - 25
frameworks/C/h2o/src/world.c

@@ -39,10 +39,14 @@
 #include "utility.h"
 #include "world.h"
 
+#define DO_CLEANUP 4
+#define DO_UPDATE 1
 #define ID_KEY "id"
+#define IS_COMPLETED 8
 #define MAX_QUERIES 500
 #define QUERIES_PARAMETER "queries="
 #define RANDOM_NUM_KEY "randomNumber"
+#define USE_CACHE 2
 
 typedef struct multiple_query_ctx_t multiple_query_ctx_t;
 typedef struct update_ctx_t update_ctx_t;
@@ -79,9 +83,7 @@ struct multiple_query_ctx_t {
 	size_t num_query;
 	size_t num_query_in_progress;
 	size_t num_result;
-	bool cleanup;
-	bool do_update;
-	bool use_cache;
+	uint_fast32_t flags;
 	query_result_t res[];
 };
 
@@ -125,12 +127,14 @@ static void cleanup_multiple_query_request(void *data)
 {
 	multiple_query_ctx_t * const query_ctx = *(multiple_query_ctx_t **) data;
 
-	if (query_ctx->cleanup) {
+	query_ctx->flags |= IS_COMPLETED;
+
+	if (query_ctx->flags & DO_CLEANUP) {
 		if (!query_ctx->num_query_in_progress)
 			cleanup_multiple_query(query_ctx);
 	}
 	else
-		query_ctx->cleanup = true;
+		query_ctx->flags |= DO_CLEANUP;
 }
 
 static void cleanup_single_query(single_query_ctx_t *query_ctx)
@@ -160,10 +164,10 @@ static void complete_multiple_query(multiple_query_ctx_t *query_ctx)
 {
 	assert(query_ctx->num_result == query_ctx->num_query);
 
-	if (query_ctx->do_update)
+	if (query_ctx->flags & DO_UPDATE)
 		do_updates(query_ctx);
 	else {
-		query_ctx->cleanup = true;
+		query_ctx->flags |= DO_CLEANUP;
 		query_ctx->gen = get_json_generator(&query_ctx->ctx->json_generator,
 		                                    &query_ctx->ctx->json_generator_num);
 
@@ -216,12 +220,14 @@ static int do_multiple_queries(bool do_update, bool use_cache, h2o_req_t *req)
 		query_ctx->ctx = ctx;
 		query_ctx->num_query = num_query;
 		query_ctx->req = req;
-		query_ctx->do_update = do_update;
-		query_ctx->use_cache = use_cache;
 		query_ctx->query_param = (query_param_t *) ((char *) query_ctx + base_size);
 		initialize_ids(num_query, query_ctx->res, &ctx->random_seed);
 
+		if (do_update)
+			query_ctx->flags |= DO_UPDATE;
+
 		if (use_cache) {
+			query_ctx->flags |= USE_CACHE;
 			fetch_from_cache(h2o_now(ctx->event_loop.h2o_ctx.loop),
 			                 &ctx->global_data->world_cache,
 			                 query_ctx);
@@ -256,7 +262,7 @@ static int do_multiple_queries(bool do_update, bool use_cache, h2o_req_t *req)
 
 			if (execute_query(ctx, &query_ctx->query_param[i].param)) {
 				query_ctx->num_query_in_progress = i;
-				query_ctx->cleanup = true;
+				query_ctx->flags |= DO_CLEANUP;
 				send_service_unavailable_error(DB_REQ_ERROR, req);
 				return 0;
 			}
@@ -318,7 +324,7 @@ static void do_updates(multiple_query_ctx_t *query_ctx)
 		goto error;
 
 	if (execute_query(query_ctx->ctx, &query_ctx->query_param->param)) {
-		query_ctx->cleanup = true;
+		query_ctx->flags |= DO_CLEANUP;
 		send_service_unavailable_error(DB_REQ_ERROR, query_ctx->req);
 	}
 	else
@@ -326,7 +332,7 @@ static void do_updates(multiple_query_ctx_t *query_ctx)
 
 	return;
 error:
-	query_ctx->cleanup = true;
+	query_ctx->flags |= DO_CLEANUP;
 	LIBRARY_ERROR("snprintf", "Truncated output.");
 	send_error(INTERNAL_SERVER_ERROR, REQ_ERROR, query_ctx->req);
 }
@@ -397,12 +403,12 @@ static void on_multiple_query_error(db_query_param_t *param, const char *error_s
 
 	query_ctx->num_query_in_progress--;
 
-	if (query_ctx->cleanup) {
-		if (!query_ctx->num_query_in_progress)
+	if (query_ctx->flags & DO_CLEANUP) {
+		if (!query_ctx->num_query_in_progress && query_ctx->flags & IS_COMPLETED)
 			cleanup_multiple_query(query_ctx);
 	}
 	else {
-		query_ctx->cleanup = true;
+		query_ctx->flags |= DO_CLEANUP;
 		send_error(BAD_GATEWAY, error_string, query_ctx->req);
 	}
 }
@@ -414,14 +420,14 @@ static result_return_t on_multiple_query_result(db_query_param_t *param, PGresul
 
 	query_ctx->num_query_in_progress--;
 
-	if (query_ctx->cleanup) {
-		if (!query_ctx->num_query_in_progress)
+	if (query_ctx->flags & DO_CLEANUP) {
+		if (!query_ctx->num_query_in_progress && query_ctx->flags & IS_COMPLETED)
 			cleanup_multiple_query(query_ctx);
 	}
 	else if (PQresultStatus(result) == PGRES_TUPLES_OK) {
 		process_result(result, query_ctx->res + query_ctx->num_result);
 
-		if (query_ctx->use_cache) {
+		if (query_ctx->flags & USE_CACHE) {
 			query_result_t * const r = malloc(sizeof(*r));
 
 			if (r) {
@@ -446,7 +452,7 @@ static result_return_t on_multiple_query_result(db_query_param_t *param, PGresul
 			query_param->id = htonl(query_ctx->res[idx].id);
 
 			if (execute_query(query_ctx->ctx, &query_param->param)) {
-				query_ctx->cleanup = true;
+				query_ctx->flags |= DO_CLEANUP;
 				send_service_unavailable_error(DB_REQ_ERROR, query_ctx->req);
 			}
 			else
@@ -456,7 +462,7 @@ static result_return_t on_multiple_query_result(db_query_param_t *param, PGresul
 			complete_multiple_query(query_ctx);
 	}
 	else {
-		query_ctx->cleanup = true;
+		query_ctx->flags |= DO_CLEANUP;
 		LIBRARY_ERROR("PQresultStatus", PQresultErrorMessage(result));
 		send_error(BAD_GATEWAY, DB_ERROR, query_ctx->req);
 	}
@@ -472,12 +478,12 @@ static void on_multiple_query_timeout(db_query_param_t *param)
 
 	query_ctx->num_query_in_progress--;
 
-	if (query_ctx->cleanup) {
-		if (!query_ctx->num_query_in_progress)
+	if (query_ctx->flags & DO_CLEANUP) {
+		if (!query_ctx->num_query_in_progress && query_ctx->flags & IS_COMPLETED)
 			cleanup_multiple_query(query_ctx);
 	}
 	else {
-		query_ctx->cleanup = true;
+		query_ctx->flags |= DO_CLEANUP;
 		send_error(GATEWAY_TIMEOUT, DB_TIMEOUT_ERROR, query_ctx->req);
 	}
 }
@@ -561,9 +567,9 @@ static result_return_t on_update_result(db_query_param_t *param, PGresult *resul
 {
 	query_param_t * const query_param = H2O_STRUCT_FROM_MEMBER(query_param_t, param, param);
 	multiple_query_ctx_t * const query_ctx = query_param->ctx;
-	const bool cleanup = query_ctx->cleanup;
+	const bool cleanup = query_ctx->flags & DO_CLEANUP;
 
-	query_ctx->cleanup = true;
+	query_ctx->flags |= DO_CLEANUP;
 	query_ctx->num_query_in_progress--;
 
 	if (cleanup)