From 89fee94686aa292bd4279a4bdffda352fe77ef2e Mon Sep 17 00:00:00 2001 From: Pavan Kumar Reddy B Date: Tue, 23 Jun 2026 16:41:54 +0530 Subject: [PATCH 1/2] eliminate session_create leaks and strengthen regression coverage --- source/jst_session.c | 14 ++++++++ tests/CMakeLists.txt | 1 + tests/parser_test.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/source/jst_session.c b/source/jst_session.c index ceec720..a6fad2a 100644 --- a/source/jst_session.c +++ b/source/jst_session.c @@ -164,6 +164,12 @@ static duk_ret_t session_create(duk_context *ctx) char* session_id = NULL; session_id = (char*)malloc(SESSION_ID_BYTES_LENGTH+1); + if(!session_id) + { + CosaPhpExtLog("Failed to allocate session_id!\n"); + RETURN_FALSE; + } + n = syscall(SYS_getrandom, bytes, SESSION_ID_BYTES_LENGTH, 0); if(n != SESSION_ID_BYTES_LENGTH) { @@ -177,16 +183,24 @@ static duk_ret_t session_create(duk_context *ctx) session_id[i] = BYTE_TO_PRINTABLE_HEX_CODE(bytes[i]); } + if(session_identifier) + { + free(session_identifier); + session_identifier = NULL; + } + session_identifier = (char*)malloc(SESSION_ID_LENGTH+1); if(!session_identifier) { CosaPhpExtLog("Failed to allocate session_identifier!\n"); + free(session_id); RETURN_FALSE; } memset(session_identifier, 0, SESSION_ID_LENGTH+1); session_id[SESSION_ID_BYTES_LENGTH] = '\0'; snprintf(session_identifier, SESSION_ID_LENGTH+1, "%s%s", SESSION_PREFIX, session_id); + free(session_id); RETURN_TRUE; return 1; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2628f71..013f6ef 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -73,6 +73,7 @@ add_executable( parser_test ../tests/parser_test.cpp ../source/jst_parser.c + ../source/jst_session.c ../source/jst_internal.c ../source/duktape/duktape.c) target_link_libraries(parser_test libgtest libgmock -pthread) diff --git a/tests/parser_test.cpp b/tests/parser_test.cpp index cd97b54..f010ab7 100644 --- a/tests/parser_test.cpp +++ b/tests/parser_test.cpp @@ -26,6 +26,10 @@ #include #include +extern "C" { + duk_ret_t ccsp_session_module_open(duk_context *ctx); +} + using namespace std; class BufferFreer @@ -106,6 +110,81 @@ TEST(general, parser) { } } +TEST(general, session_create_multiple_calls_succeed) +{ + duk_context* ctx = duk_create_heap_default(); + ASSERT_NE(ctx, nullptr); + + duk_push_c_function(ctx, ccsp_session_module_open, 0); + duk_call(ctx, 0); + duk_put_global_string(ctx, "ccsp_session"); + + duk_get_global_string(ctx, "ccsp_session"); + duk_get_prop_string(ctx, -1, "create"); + ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS); + EXPECT_TRUE(duk_get_boolean(ctx, -1)); + duk_pop_2(ctx); + + duk_get_global_string(ctx, "ccsp_session"); + duk_get_prop_string(ctx, -1, "create"); + ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS); + EXPECT_TRUE(duk_get_boolean(ctx, -1)); + duk_pop_2(ctx); + + duk_get_global_string(ctx, "ccsp_session"); + duk_get_prop_string(ctx, -1, "destroy"); + ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS); + EXPECT_TRUE(duk_get_boolean(ctx, -1)); + duk_pop_2(ctx); + + duk_destroy_heap(ctx); +} + +TEST(general, session_create_destroy_cycle_and_id_format) +{ + duk_context* ctx = duk_create_heap_default(); + ASSERT_NE(ctx, nullptr); + + duk_push_c_function(ctx, ccsp_session_module_open, 0); + duk_call(ctx, 0); + duk_put_global_string(ctx, "ccsp_session"); + + duk_get_global_string(ctx, "ccsp_session"); + duk_get_prop_string(ctx, -1, "create"); + ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS); + EXPECT_TRUE(duk_get_boolean(ctx, -1)); + duk_pop_2(ctx); + + duk_get_global_string(ctx, "ccsp_session"); + duk_get_prop_string(ctx, -1, "getId"); + ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS); + const char* first_id = duk_get_string(ctx, -1); + ASSERT_NE(first_id, nullptr); + EXPECT_EQ(strlen(first_id), 40u); + EXPECT_EQ(strncmp(first_id, "jst_sess", 8), 0); + duk_pop_2(ctx); + + duk_get_global_string(ctx, "ccsp_session"); + duk_get_prop_string(ctx, -1, "destroy"); + ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS); + EXPECT_TRUE(duk_get_boolean(ctx, -1)); + duk_pop_2(ctx); + + duk_get_global_string(ctx, "ccsp_session"); + duk_get_prop_string(ctx, -1, "create"); + ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS); + EXPECT_TRUE(duk_get_boolean(ctx, -1)); + duk_pop_2(ctx); + + duk_get_global_string(ctx, "ccsp_session"); + duk_get_prop_string(ctx, -1, "destroy"); + ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS); + EXPECT_TRUE(duk_get_boolean(ctx, -1)); + duk_pop_2(ctx); + + duk_destroy_heap(ctx); +} + int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); From 37c6066e6829726b023976492d1f821e44356790 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Reddy B Date: Tue, 23 Jun 2026 17:12:53 +0530 Subject: [PATCH 2/2] fix(session): unlink stale session file on recreate; harden test module-open calls --- source/jst_session.c | 3 +++ tests/parser_test.cpp | 19 ++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/source/jst_session.c b/source/jst_session.c index a6fad2a..69f542f 100644 --- a/source/jst_session.c +++ b/source/jst_session.c @@ -185,6 +185,9 @@ static duk_ret_t session_create(duk_context *ctx) if(session_identifier) { + char filename[SESSION_FILE_MAX_PATH]; + snprintf(filename, SESSION_FILE_MAX_PATH, "%s/%s", SESSION_TMP_DIR, session_identifier); + unlink(filename); free(session_identifier); session_identifier = NULL; } diff --git a/tests/parser_test.cpp b/tests/parser_test.cpp index f010ab7..a3bc427 100644 --- a/tests/parser_test.cpp +++ b/tests/parser_test.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "jst.h" #include #include @@ -116,7 +117,7 @@ TEST(general, session_create_multiple_calls_succeed) ASSERT_NE(ctx, nullptr); duk_push_c_function(ctx, ccsp_session_module_open, 0); - duk_call(ctx, 0); + ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS); duk_put_global_string(ctx, "ccsp_session"); duk_get_global_string(ctx, "ccsp_session"); @@ -146,7 +147,7 @@ TEST(general, session_create_destroy_cycle_and_id_format) ASSERT_NE(ctx, nullptr); duk_push_c_function(ctx, ccsp_session_module_open, 0); - duk_call(ctx, 0); + ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS); duk_put_global_string(ctx, "ccsp_session"); duk_get_global_string(ctx, "ccsp_session"); @@ -162,20 +163,24 @@ TEST(general, session_create_destroy_cycle_and_id_format) ASSERT_NE(first_id, nullptr); EXPECT_EQ(strlen(first_id), 40u); EXPECT_EQ(strncmp(first_id, "jst_sess", 8), 0); - duk_pop_2(ctx); - duk_get_global_string(ctx, "ccsp_session"); - duk_get_prop_string(ctx, -1, "destroy"); - ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS); - EXPECT_TRUE(duk_get_boolean(ctx, -1)); + char first_session_file[128] = {0}; + snprintf(first_session_file, sizeof(first_session_file), "/tmp/%s", first_id); duk_pop_2(ctx); + FILE* stale = fopen(first_session_file, "w"); + ASSERT_NE(stale, nullptr); + fclose(stale); + ASSERT_EQ(access(first_session_file, F_OK), 0); + duk_get_global_string(ctx, "ccsp_session"); duk_get_prop_string(ctx, -1, "create"); ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS); EXPECT_TRUE(duk_get_boolean(ctx, -1)); duk_pop_2(ctx); + EXPECT_NE(access(first_session_file, F_OK), 0); + duk_get_global_string(ctx, "ccsp_session"); duk_get_prop_string(ctx, -1, "destroy"); ASSERT_EQ(duk_pcall(ctx, 0), DUK_EXEC_SUCCESS);