From 7b10b9ea3100d11e75503cfeea617d18685a4ec0 Mon Sep 17 00:00:00 2001 From: BP Cheng Date: Mon, 26 Jan 2026 20:49:31 -0800 Subject: [PATCH] config_format: cf_yaml: fix Windows crash when libyaml is loaded as DLL On Windows, passing FILE* across DLL boundaries can cause crashes due to different C runtime libraries having incompatible internal FILE structures. When libyaml is built as a dynamic library (DLL), using yaml_parser_set_input_file() causes the FILE* pointer to cross the DLL boundary, leading to memory corruption or crashes. This fix reads the YAML config file into a memory buffer and uses yaml_parser_set_input_string() instead of yaml_parser_set_input_file(), avoiding the cross-DLL FILE* issue. Changes: - Open file in binary mode ("rb") for consistent behavior - Read entire file content into a buffer using fseek/ftell/fread - Use yaml_parser_set_input_string() with the buffer - Properly free the buffer after parsing Signed-off-by: bpcheng@hotmail.com Signed-off-by: BP Cheng --- src/config_format/flb_cf_yaml.c | 48 ++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/config_format/flb_cf_yaml.c b/src/config_format/flb_cf_yaml.c index 916093368d9..8757bef2a59 100644 --- a/src/config_format/flb_cf_yaml.c +++ b/src/config_format/flb_cf_yaml.c @@ -2905,7 +2905,7 @@ static int read_config(struct flb_cf *conf, struct local_ctx *ctx, } flb_debug("============ %s ============", cfg_file); - fh = fopen(include_file, "r"); + fh = fopen(include_file, "rb"); if (!fh) { flb_errno(); @@ -2925,9 +2925,48 @@ static int read_config(struct flb_cf *conf, struct local_ctx *ctx, return -1; } ctx->level++; + + /* + * On Windows, passing FILE* across DLL boundaries can cause crashes due to + * different C runtime libraries. Read the file into a buffer and use + * yaml_parser_set_input_string() instead of yaml_parser_set_input_file(). + */ + { + long file_size; + unsigned char *file_buffer = NULL; + size_t bytes_read; + + /* Get file size */ + fseek(fh, 0, SEEK_END); + file_size = ftell(fh); + fseek(fh, 0, SEEK_SET); + + if (file_size < 0) { + flb_error("[config] could not determine file size for %s", cfg_file); + fclose(fh); + flb_sds_destroy(include_dir); + flb_sds_destroy(include_file); + return -1; + } + /* Allocate buffer */ + file_buffer = flb_malloc(file_size + 1); + if (!file_buffer) { + flb_error("[config] could not allocate memory for config file %s", cfg_file); + fclose(fh); + flb_sds_destroy(include_dir); + flb_sds_destroy(include_file); + return -1; + } + + /* Read file content */ + bytes_read = fread(file_buffer, 1, file_size, fh); + fclose(fh); + fh = NULL; /* Mark as closed */ + file_buffer[bytes_read] = '\0'; + yaml_parser_initialize(&parser); - yaml_parser_set_input_file(&parser, fh); + yaml_parser_set_input_string(&parser, file_buffer, bytes_read); do { status = yaml_parser_parse(&parser, &event); @@ -2990,7 +3029,10 @@ static int read_config(struct flb_cf *conf, struct local_ctx *ctx, state = state_pop(ctx); } - fclose(fh); + /* Free the file buffer that was allocated for yaml_parser_set_input_string */ + flb_free(file_buffer); + } /* End of block that declared file_buffer */ + ctx->level--; flb_sds_destroy(include_file);