diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root new file mode 120000 index 0000000..945c9b4 --- /dev/null +++ b/_codeql_detected_source_root @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/include/ut_kvp.h b/include/ut_kvp.h index f2fa326..df9ee51 100644 --- a/include/ut_kvp.h +++ b/include/ut_kvp.h @@ -92,13 +92,15 @@ ut_kvp_status_t ut_kvp_open(ut_kvp_instance_t *pInstance, char *fileName); * @param[in] pInstance Destination KVP instance (created with `ut_kvp_createInstance()`). * @param[in] pData Caller-owned buffer containing the serialized KVP payload (text). * @param[in] length Size of `pData` in bytes (use `strlen(pData)+1` for text). + * @param[in] base_dir Optional base directory for resolving relative include paths (can be NULL). + * If NULL, relative includes will be resolved from CWD. * * @retval UT_KVP_STATUS_SUCCESS Parsed successfully. * @retval UT_KVP_STATUS_INVALID_PARAM Invalid pointer/length. * @retval UT_KVP_STATUS_PARSING_ERROR Malformed payload. * @retval UT_KVP_STATUS_INVALID_INSTANCE Invalid destination instance. */ -ut_kvp_status_t ut_kvp_openMemory(ut_kvp_instance_t *pInstance, char *pData, uint32_t length); +ut_kvp_status_t ut_kvp_openMemory(ut_kvp_instance_t *pInstance, char *pData, uint32_t length, const char *base_dir); /**! * @brief Closes a previously opened KVP profile and frees its memory. diff --git a/src/ut_kvp.c b/src/ut_kvp.c index fa50fc7..6599d5f 100644 --- a/src/ut_kvp.c +++ b/src/ut_kvp.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include /* Application Includes */ #include @@ -57,9 +59,9 @@ static bool str_to_bool(const char *string); static ut_kvp_status_t ut_kvp_getField(ut_kvp_instance_t *pInstance, const char *pszKey, char *pszResult); static void convert_dot_to_slash(const char *key, char *output); static size_t write_memory_callback(void *contents, size_t size, size_t nmemb, void *userp); -static struct fy_node* process_include(const char *filename, int depth, struct fy_document *doc); +static struct fy_node* process_include(const char *filename, int depth, struct fy_document *doc, const char *base_dir); static void merge_nodes(struct fy_node *mainNode, struct fy_node *includeNode); -static struct fy_node* process_node_copy(struct fy_node *srcNode, struct fy_document *dstDoc, int depth); +static struct fy_node* process_node_copy(struct fy_node *srcNode, struct fy_document *dstDoc, int depth, const char *base_dir); static const void *find_pattern_from_buffer(const void *buffer, size_t bufferLength, const void *pattern, size_t patternLength); ut_kvp_instance_t *ut_kvp_createInstance(void) @@ -115,8 +117,25 @@ ut_kvp_status_t ut_kvp_open(ut_kvp_instance_t *pInstance, char *fileName) return UT_KVP_STATUS_FILE_OPEN_ERROR; } + // Resolve to absolute path + char resolved_path[PATH_MAX]; + if (realpath(fileName, resolved_path) == NULL) + { + UT_LOG_ERROR("Failed to resolve path [%s]", fileName); + return UT_KVP_STATUS_FILE_OPEN_ERROR; + } + + // Extract base directory from the resolved path for relative includes + char *resolved_copy = strdup(resolved_path); + if (resolved_copy == NULL) + { + UT_LOG_ERROR("Memory allocation failure"); + return UT_KVP_STATUS_PARSING_ERROR; + } + char *base_dir = dirname(resolved_copy); + // Load the new document - struct fy_document *newDoc = fy_document_build_from_file(NULL, fileName); + struct fy_document *newDoc = fy_document_build_from_file(NULL, resolved_path); if (newDoc == NULL || fy_document_resolve(newDoc) != 0) { if (newDoc) @@ -124,6 +143,7 @@ ut_kvp_status_t ut_kvp_open(ut_kvp_instance_t *pInstance, char *fileName) UT_LOG_ERROR("Error resolving document for anchors, aliases and merge keys"); fy_document_destroy(newDoc); } + free(resolved_copy); ut_kvp_close(pInstance); return UT_KVP_STATUS_PARSING_ERROR; } @@ -134,6 +154,7 @@ ut_kvp_status_t ut_kvp_open(ut_kvp_instance_t *pInstance, char *fileName) { UT_LOG_ERROR("Unable to get root node from document"); fy_document_destroy(newDoc); + free(resolved_copy); ut_kvp_close(pInstance); return UT_KVP_STATUS_PARSING_ERROR; } @@ -147,17 +168,19 @@ ut_kvp_status_t ut_kvp_open(ut_kvp_instance_t *pInstance, char *fileName) { UT_LOG_ERROR("Unable to create doc"); fy_document_destroy(newDoc); + free(resolved_copy); ut_kvp_close(pInstance); return UT_KVP_STATUS_PARSING_ERROR; } } - // Always process includes via process_node_copy - struct fy_node *copiedRoot = process_node_copy(newRoot, pInternal->fy_handle, 0); + // Always process includes via process_node_copy with base directory context + struct fy_node *copiedRoot = process_node_copy(newRoot, pInternal->fy_handle, 0, base_dir); if (copiedRoot == NULL) { UT_LOG_ERROR("Unable to process node"); fy_document_destroy(newDoc); + free(resolved_copy); ut_kvp_close(pInstance); return UT_KVP_STATUS_PARSING_ERROR; } @@ -177,15 +200,16 @@ ut_kvp_status_t ut_kvp_open(ut_kvp_instance_t *pInstance, char *fileName) } fy_document_destroy(newDoc); + free(resolved_copy); return UT_KVP_STATUS_SUCCESS; } -ut_kvp_status_t ut_kvp_openMemory(ut_kvp_instance_t *pInstance, char *pData, uint32_t length ) +ut_kvp_status_t ut_kvp_openMemory(ut_kvp_instance_t *pInstance, char *pData, uint32_t length, const char *base_dir) { struct fy_node *node; ut_kvp_instance_internal_t *pInternal = validateInstance(pInstance); - char *cData = NULL; + size_t actual_length; if (pInstance == NULL) { @@ -198,19 +222,45 @@ ut_kvp_status_t ut_kvp_openMemory(ut_kvp_instance_t *pInstance, char *pData, uin return UT_KVP_STATUS_INVALID_PARAM; } - cData = strdup((const char*)pData); + // Handle -1 as a special value meaning "use strlen" + if (length == (uint32_t)-1) + { + actual_length = strlen(pData); + } + else + { + actual_length = length; + } - if (cData == NULL) + // Write pData to a temporary file to avoid memory leak with fy_document_build_from_malloc_string + FILE *tmp = tmpfile(); + if (!tmp) { - UT_LOG_ERROR("Memory allocation failure"); + UT_LOG_ERROR("Failed to create temporary file"); return UT_KVP_STATUS_PARSING_ERROR; } - struct fy_document *srcDoc = fy_document_build_from_malloc_string(NULL, cData, length); + size_t written = fwrite(pData, 1, actual_length, tmp); + if (written != actual_length) + { + UT_LOG_ERROR("Failed to write all data to temporary file"); + fclose(tmp); + return UT_KVP_STATUS_PARSING_ERROR; + } + fflush(tmp); + rewind(tmp); - if(fy_document_resolve(srcDoc) != 0) + struct fy_document *srcDoc = fy_document_build_from_fp(NULL, tmp); + //using this instead of fy_document_build_from_malloc_string(), as the malloced string was not getting freed at fy_document_destroy() + + if (srcDoc == NULL || fy_document_resolve(srcDoc) != 0) { - UT_LOG_ERROR("Error resolving document for anchors, aliases and merge keys"); + if (srcDoc) + { + UT_LOG_ERROR("Error resolving document for anchors, aliases and merge keys"); + fy_document_destroy(srcDoc); + } + fclose(tmp); ut_kvp_close(pInstance); return UT_KVP_STATUS_PARSING_ERROR; } @@ -227,23 +277,27 @@ ut_kvp_status_t ut_kvp_openMemory(ut_kvp_instance_t *pInstance, char *pData, uin UT_LOG_ERROR("Unable to parse file/memory"); ut_kvp_close(pInstance); fy_document_destroy(srcDoc); + fclose(tmp); return UT_KVP_STATUS_PARSING_ERROR; } } struct fy_node *srcNode = fy_document_root(srcDoc); - node = process_node_copy(srcNode, pInternal->fy_handle, 0); + // Pass base_dir for resolving relative includes; if NULL, will fall back to CWD + node = process_node_copy(srcNode, pInternal->fy_handle, 0, base_dir); if (node == NULL) { UT_LOG_ERROR("Unable to process node"); ut_kvp_close(pInstance); fy_document_destroy(srcDoc); + fclose(tmp); return UT_KVP_STATUS_PARSING_ERROR; } fy_document_set_root(pInternal->fy_handle, node); fy_document_destroy(srcDoc); + fclose(tmp); return UT_KVP_STATUS_SUCCESS; } @@ -910,7 +964,7 @@ static size_t write_memory_callback(void *contents, size_t size, size_t nmemb, v return realsize; } -static struct fy_node* process_node_copy(struct fy_node *srcNode, struct fy_document *dstDoc, int depth) +static struct fy_node* process_node_copy(struct fy_node *srcNode, struct fy_document *dstDoc, int depth, const char *base_dir) { if (srcNode == NULL || dstDoc == NULL) { @@ -932,10 +986,10 @@ static struct fy_node* process_node_copy(struct fy_node *srcNode, struct fy_docu const char *filepath = fy_node_get_scalar(srcNode, NULL); if (filepath) { - struct fy_node *included = process_include(filepath, depth, dstDoc); + struct fy_node *included = process_include(filepath, depth, dstDoc, base_dir); if (included) { - return process_node_copy(included, dstDoc, depth + 1); + return process_node_copy(included, dstDoc, depth + 1, base_dir); } } return NULL; @@ -971,16 +1025,16 @@ static struct fy_node* process_node_copy(struct fy_node *srcNode, struct fy_docu const char *filepath = fy_node_get_scalar(incl, NULL); if (filepath) { - struct fy_node *included = process_include(filepath, depth, dstDoc); + struct fy_node *included = process_include(filepath, depth, dstDoc, base_dir); if (included) - copied_entry = process_node_copy(included, dstDoc, depth + 1); + copied_entry = process_node_copy(included, dstDoc, depth + 1, base_dir); } } } if (copied_entry == NULL) { - copied_entry = process_node_copy(entry, dstDoc, depth); + copied_entry = process_node_copy(entry, dstDoc, depth, base_dir); } if (copied_entry) @@ -1023,7 +1077,7 @@ static struct fy_node* process_node_copy(struct fy_node *srcNode, struct fy_docu const char *filepath = fy_node_get_scalar(val_node, NULL); if (filepath) { - struct fy_node *included = process_include(filepath, depth, dstDoc); + struct fy_node *included = process_include(filepath, depth, dstDoc, base_dir); if (included) { // If the included node is a mapping, merge it into the new_map @@ -1035,7 +1089,7 @@ static struct fy_node* process_node_copy(struct fy_node *srcNode, struct fy_docu // Regular case: recursive copy struct fy_node *copied_key = fy_node_copy(dstDoc, key_node); - struct fy_node *copied_val = process_node_copy(val_node, dstDoc, depth); + struct fy_node *copied_val = process_node_copy(val_node, dstDoc, depth, base_dir); if (copied_key && copied_val) { @@ -1099,7 +1153,7 @@ static void merge_nodes(struct fy_node *mainNode, struct fy_node *includeNode) } } -static struct fy_node* process_include(const char *filename, int depth, struct fy_document *doc) +static struct fy_node* process_include(const char *filename, int depth, struct fy_document *doc, const char *base_dir) { ut_kvp_download_memory_internal_t mChunk; @@ -1185,7 +1239,7 @@ static struct fy_node* process_include(const char *filename, int depth, struct f } struct fy_node *srcNode = fy_document_root(srcDoc); - struct fy_node *root = process_node_copy(srcNode, doc, depth + 1); + struct fy_node *root = process_node_copy(srcNode, doc, depth + 1, base_dir); fy_document_destroy(srcDoc); fclose(tmp); @@ -1195,28 +1249,92 @@ static struct fy_node* process_include(const char *filename, int depth, struct f } else { - // Local file include - FILE *file = fopen(filename, "r"); + // Local file include - resolve relative paths + char resolved_path[PATH_MAX]; + char *final_path = NULL; + + // Check if the path is absolute + if (filename[0] == '/') + { + // Absolute path - use realpath to normalize it + if (realpath(filename, resolved_path) != NULL) + { + final_path = resolved_path; + } + else + { + UT_LOG_ERROR("Failed to resolve absolute path '%s'", filename); + return NULL; + } + } + else + { + // Relative path - resolve relative to base directory + if (base_dir != NULL) + { + // Construct full path: base_dir/filename + char temp_path[PATH_MAX]; + snprintf(temp_path, sizeof(temp_path), "%s/%s", base_dir, filename); + + // Resolve to absolute path + if (realpath(temp_path, resolved_path) != NULL) + { + final_path = resolved_path; + } + else + { + UT_LOG_ERROR("Failed to resolve relative path '%s' from base directory '%s'", filename, base_dir); + return NULL; + } + } + else + { + // No base directory - try resolving relative to CWD as fallback + if (realpath(filename, resolved_path) != NULL) + { + final_path = resolved_path; + } + else + { + UT_LOG_ERROR("Failed to resolve path '%s'", filename); + return NULL; + } + } + } + + FILE *file = fopen(final_path, "r"); if (!file) { - UT_LOG_ERROR("Error: Cannot open include file '%s'.\n", filename); + UT_LOG_ERROR("Cannot open include file '%s'", final_path); return NULL; } - // struct fy_document *doc; - struct fy_document *srcDoc = fy_document_build_from_file(NULL, filename); + struct fy_document *srcDoc = fy_document_build_from_file(NULL, final_path); if (srcDoc == NULL) { - UT_LOG_ERROR("Error: Cannot parse include file '%s'.\n", filename); + UT_LOG_ERROR("Cannot parse include file '%s'", final_path); fclose(file); return NULL; } - struct fy_node *root; + // Extract base directory from the resolved include file path for nested includes + char *resolved_copy = strdup(final_path); + if (resolved_copy == NULL) + { + UT_LOG_ERROR("Memory allocation failure"); + fclose(file); + fy_document_destroy(srcDoc); + return NULL; + } + char *include_base_dir = dirname(resolved_copy); + struct fy_node *srcNode = fy_document_root(srcDoc); - root = process_node_copy(srcNode, doc, depth + 1); + struct fy_node *root = process_node_copy(srcNode, doc, depth + 1, include_base_dir); + fclose(file); fy_document_destroy(srcDoc); + free(resolved_copy); + return root; } } diff --git a/tests/src/assets/include/2d.yaml b/tests/src/assets/include/2d.yaml index b8cad0c..f94be76 100644 --- a/tests/src/assets/include/2d.yaml +++ b/tests/src/assets/include/2d.yaml @@ -1,4 +1,4 @@ --- "2": value: true -include: assets/include/3d.yaml +include: 3d.yaml diff --git a/tests/src/assets/include/3d.yaml b/tests/src/assets/include/3d.yaml index 4b9f675..e87c675 100644 --- a/tests/src/assets/include/3d.yaml +++ b/tests/src/assets/include/3d.yaml @@ -1,4 +1,4 @@ --- "3": value: true -include: assets/include/4d.yaml +include: 4d.yaml diff --git a/tests/src/assets/include/4d.yaml b/tests/src/assets/include/4d.yaml index 7d1f3c3..3caec9e 100644 --- a/tests/src/assets/include/4d.yaml +++ b/tests/src/assets/include/4d.yaml @@ -1,4 +1,4 @@ --- "4": value: true -include: assets/include/5d.yaml +include: 5d.yaml diff --git a/tests/src/assets/include/depth_check.yaml b/tests/src/assets/include/depth_check.yaml index 2f4fb63..34df362 100644 --- a/tests/src/assets/include/depth_check.yaml +++ b/tests/src/assets/include/depth_check.yaml @@ -1,4 +1,4 @@ --- "1": value: true -include: assets/include/2d.yaml +include: 2d.yaml diff --git a/tests/src/assets/include/sequence-include.yaml b/tests/src/assets/include/sequence-include.yaml index b8795ef..ec2e2af 100644 --- a/tests/src/assets/include/sequence-include.yaml +++ b/tests/src/assets/include/sequence-include.yaml @@ -2,7 +2,7 @@ "1": value: true plugin: - - include: assets/include/2s.yaml + - include: 2s.yaml - include: https://raw.githubusercontent.com/rdkcentral/ut-control/main/tests/src/assets/include/3s.yaml -include_0: assets/include/4s.yaml +include_0: 4s.yaml include_1: https://raw.githubusercontent.com/rdkcentral/ut-control/main/tests/src/assets/include/5s.yaml \ No newline at end of file diff --git a/tests/src/assets/include/single-include-file.yaml b/tests/src/assets/include/single-include-file.yaml index ff53022..4b073e6 100644 --- a/tests/src/assets/include/single-include-file.yaml +++ b/tests/src/assets/include/single-include-file.yaml @@ -1,23 +1,23 @@ --- "1": value: true -include_0: assets/include/2s.yaml -include_1: assets/include/3s.yaml -include_2: assets/include/4s.yaml -include_3: assets/include/5s.yaml -include_4: assets/include/6s.yaml -include_5: assets/include/7s.yaml -include_6: assets/include/8s.yaml -include_7: assets/include/9s.yaml -include_8: assets/include/10s.yaml -include_9: assets/include/11s.yaml -include_10: assets/include/12s.yaml -include_11: assets/include/13s.yaml -include_12: assets/include/14s.yaml -include_13: assets/include/15s.yaml -include_14: assets/include/16s.yaml -include_15: assets/include/17s.yaml -include_16: assets/include/18s.yaml -include_17: assets/include/19s.yaml -include_18: assets/include/20s.yaml -include_19: assets/include/21s.yaml \ No newline at end of file +include_0: 2s.yaml +include_1: 3s.yaml +include_2: 4s.yaml +include_3: 5s.yaml +include_4: 6s.yaml +include_5: 7s.yaml +include_6: 8s.yaml +include_7: 9s.yaml +include_8: 10s.yaml +include_9: 11s.yaml +include_10: 12s.yaml +include_11: 13s.yaml +include_12: 14s.yaml +include_13: 15s.yaml +include_14: 16s.yaml +include_15: 17s.yaml +include_16: 18s.yaml +include_17: 19s.yaml +include_18: 20s.yaml +include_19: 21s.yaml \ No newline at end of file diff --git a/tests/src/assets/yaml_tags.yaml b/tests/src/assets/yaml_tags.yaml index bd74197..4afd00b 100644 --- a/tests/src/assets/yaml_tags.yaml +++ b/tests/src/assets/yaml_tags.yaml @@ -2,7 +2,7 @@ "1": value: true plugin: - - !include assets/include/2s.yaml - - !include assets/include/3s.yaml -"10": !include assets/include/4s.yaml -"11": !include assets/include/5s.yaml \ No newline at end of file + - !include include/2s.yaml + - !include include/3s.yaml +"10": !include include/4s.yaml +"11": !include include/5s.yaml \ No newline at end of file diff --git a/tests/src/assets/yaml_tags_in_sequence.yaml b/tests/src/assets/yaml_tags_in_sequence.yaml index 8d55f59..dcddd2c 100644 --- a/tests/src/assets/yaml_tags_in_sequence.yaml +++ b/tests/src/assets/yaml_tags_in_sequence.yaml @@ -1,9 +1,9 @@ # A single scalar value included from an external source configItem: - value: !include assets/include/2s.yaml + value: !include include/2s.yaml # A list of values, each included from a separate external source listConfig: valueList: - - !include assets/include/3s.yaml - - !include assets/include/4s.yaml \ No newline at end of file + - !include include/3s.yaml + - !include include/4s.yaml \ No newline at end of file diff --git a/tests/src/ut_test_kvp.c b/tests/src/ut_test_kvp.c index c0535f6..9b531e8 100644 --- a/tests/src/ut_test_kvp.c +++ b/tests/src/ut_test_kvp.c @@ -159,12 +159,12 @@ void test_ut_kvp_open_memory( void ) /* Negative Read Test, NULL params passed in both args*/ UT_LOG_STEP("ut_kvp_openMemory( NULL, NULL, -1 )"); - status = ut_kvp_openMemory( NULL, NULL, -1); + status = ut_kvp_openMemory( NULL, NULL, -1, NULL); UT_ASSERT( status == UT_KVP_STATUS_INVALID_INSTANCE ); /* Negative Read Test, NULL PARAM passed in 2nd arg */ UT_LOG_STEP("ut_kvp_openMemory( gpMainTestInstance, NULL, -1 ) - Negative"); - status = ut_kvp_openMemory( gpMainTestInstance, NULL, -1); + status = ut_kvp_openMemory( gpMainTestInstance, NULL, -1, NULL); UT_ASSERT( status == UT_KVP_STATUS_INVALID_PARAM ); /* data doesn't exist */ @@ -173,7 +173,7 @@ void test_ut_kvp_open_memory( void ) gKVPData.buffer = strdup(kvp_str); if (gKVPData.buffer) { - status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, -1); + status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, -1, NULL); UT_ASSERT(status == UT_KVP_STATUS_PARSING_ERROR); free(gKVPData.buffer); } @@ -182,7 +182,7 @@ void test_ut_kvp_open_memory( void ) UT_LOG_STEP("ut_kvp_openMemory( gpMainTestInstance, %s - zero length file ) - Negative", KVP_VALID_TEST_ZERO_LENGTH_YAML_FILE); if (read_file_into_memory(KVP_VALID_TEST_ZERO_LENGTH_YAML_FILE, &gKVPData) == 0) { - status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length); + status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length, NULL); UT_ASSERT(status == UT_KVP_STATUS_PARSING_ERROR); free(gKVPData.buffer); gKVPData.length = 0; @@ -192,7 +192,7 @@ void test_ut_kvp_open_memory( void ) UT_LOG_STEP("ut_kvp_openMemory( gpMainTestInstance, %s ) - Positive", KVP_VALID_TEST_YAML_FILE); if (read_file_into_memory(KVP_VALID_TEST_YAML_FILE, &gKVPData) == 0) { - status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length); + status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length, NULL); UT_ASSERT(status == UT_KVP_STATUS_SUCCESS); free(gKVPData.buffer); gKVPData.length = 0; @@ -201,7 +201,7 @@ void test_ut_kvp_open_memory( void ) UT_LOG_STEP("ut_kvp_openMemory( gpMainTestInstance, %s ) - Postive", KVP_VALID_TEST_NOT_VALID_YAML_FORMATTED_FILE); if (read_file_into_memory(KVP_VALID_TEST_NOT_VALID_YAML_FORMATTED_FILE, &gKVPData) == 0) { - status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length); + status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length, NULL); UT_ASSERT(status == UT_KVP_STATUS_SUCCESS); free(gKVPData.buffer); gKVPData.length = 0; @@ -210,7 +210,7 @@ void test_ut_kvp_open_memory( void ) UT_LOG_STEP("ut_kvp_openMemory( gpMainTestInstance, %s ) - Postive", KVP_VALID_TEST_JSON_FILE); if (read_file_into_memory(KVP_VALID_TEST_JSON_FILE, &gKVPData) == 0) { - status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length); + status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length, NULL); UT_ASSERT(status == UT_KVP_STATUS_SUCCESS); free(gKVPData.buffer); gKVPData.length = 0; @@ -848,7 +848,7 @@ void test_ut_kvp_add_multiple_profile_using_open_memory(void) UT_LOG_STEP("ut_kvp_openMemory( gpMainTestInstance, %s ) - Postive", KVP_VALID_TEST_YAML_CONFIG_FILE); if (read_file_into_memory(KVP_VALID_TEST_YAML_CONFIG_FILE, &gKVPData) == 0) { - status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length); + status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length, NULL); UT_ASSERT(status == UT_KVP_STATUS_SUCCESS); free(gKVPData.buffer); gKVPData.length = 0; @@ -857,7 +857,7 @@ void test_ut_kvp_add_multiple_profile_using_open_memory(void) UT_LOG_STEP("ut_kvp_openMemory( gpMainTestInstance, %s ) - Postive", KVP_VALID_TEST_SINGLE_INCLUDE_FILE_YAML); if (read_file_into_memory(KVP_VALID_TEST_SINGLE_INCLUDE_FILE_YAML, &gKVPData) == 0) { - status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length); + status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length, NULL); UT_ASSERT(status == UT_KVP_STATUS_SUCCESS); free(gKVPData.buffer); gKVPData.length = 0; @@ -866,7 +866,7 @@ void test_ut_kvp_add_multiple_profile_using_open_memory(void) UT_LOG_STEP("ut_kvp_openMemory( gpMainTestInstance, %s ) - Postive", KVP_VALID_TEST_DEPTH_CHECK_INCLUDE_YAML); if (read_file_into_memory(KVP_VALID_TEST_DEPTH_CHECK_INCLUDE_YAML, &gKVPData) == 0) { - status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length); + status = ut_kvp_openMemory(gpMainTestInstance, gKVPData.buffer, gKVPData.length, NULL); UT_ASSERT(status == UT_KVP_STATUS_SUCCESS); free(gKVPData.buffer); gKVPData.length = 0; @@ -976,6 +976,8 @@ static void create_delete_kvp_memory_instance_for_given_file(const char* filenam ut_kvp_instance_t *pInstance = NULL; ut_kvp_status_t status = UT_KVP_STATUS_MAX; char* kvpData; + char *base_dir = NULL; + char *filename_copy = NULL; pInstance = ut_kvp_createInstance(); if ( pInstance == NULL ) @@ -985,14 +987,26 @@ static void create_delete_kvp_memory_instance_for_given_file(const char* filenam return; } + // Extract base directory from filename for resolving relative includes + filename_copy = strdup(filename); + if (filename_copy != NULL) + { + base_dir = dirname(filename_copy); + } + if (read_file_into_memory(filename, &kvpMemory) == 0) { - status = ut_kvp_openMemory(pInstance, kvpMemory.buffer, kvpMemory.length); + status = ut_kvp_openMemory(pInstance, kvpMemory.buffer, kvpMemory.length, base_dir); UT_ASSERT(status == UT_KVP_STATUS_SUCCESS); free(kvpMemory.buffer); kvpMemory.length = 0; } + if (filename_copy != NULL) + { + free(filename_copy); + } + if ( status != UT_KVP_STATUS_SUCCESS ) { UT_LOG_ERROR("ut_kvp_open() - Read Failure"); @@ -1131,7 +1145,7 @@ static int test_ut_kvp_createGlobalYAMLInstanceForMallocedData( void ) if (read_file_into_memory(KVP_VALID_TEST_YAML_FILE, &kvpMemory) == 0) { - status = ut_kvp_openMemory(gpMainTestInstance, kvpMemory.buffer, kvpMemory.length); + status = ut_kvp_openMemory(gpMainTestInstance, kvpMemory.buffer, kvpMemory.length, NULL); assert(status == UT_KVP_STATUS_SUCCESS); free(kvpMemory.buffer); kvpMemory.length = 0; @@ -1161,7 +1175,7 @@ static int test_ut_kvp_createGlobalJSONInstanceForMallocedData( void ) if (read_file_into_memory(KVP_VALID_TEST_JSON_FILE, &kvpMemory) == 0) { - status = ut_kvp_openMemory(gpMainTestInstance, kvpMemory.buffer, kvpMemory.length); + status = ut_kvp_openMemory(gpMainTestInstance, kvpMemory.buffer, kvpMemory.length, NULL); assert(status == UT_KVP_STATUS_SUCCESS); free(kvpMemory.buffer); kvpMemory.length = 0;