diff --git a/src/pcre2_compile_class.c b/src/pcre2_compile_class.c index 9a1fc022f..55b641c19 100644 --- a/src/pcre2_compile_class.c +++ b/src/pcre2_compile_class.c @@ -1802,17 +1802,14 @@ if ((xclass_props & XCLASS_REQUIRED) != 0) PUT(code, 0, (uint32_t)(char_lists_size >> 1)); code += LINK_SIZE; -#if defined PCRE2_DEBUG || defined SUPPORT_VALGRIND + /* If we added padding to align the list, initialize the bytes to + defined values, so the library is valgrind-clean. It could also + be a security concern for clients calling into PCRE2 via bindings + from a memory-safe language, if pcre2_serialize_encode() exposes + uninitialized memory that may contain sensitive information. */ + if ((char_lists_size & 0x2) != 0) - { - /* In debug the unused 16 bit value is set - to a fixed value and marked unused. */ - ((uint16_t*)data)[-1] = 0x5555; -#ifdef SUPPORT_VALGRIND - VALGRIND_MAKE_MEM_NOACCESS(data - 2, 2); -#endif - } -#endif + ((uint16_t*)data)[-1] = 0xdead; cb->char_lists_size = CLIST_ALIGN_TO(char_lists_size, sizeof(uint32_t)); diff --git a/src/pcre2test_inc.h b/src/pcre2test_inc.h index 8124e9ca6..c47074171 100644 --- a/src/pcre2test_inc.h +++ b/src/pcre2test_inc.h @@ -2019,6 +2019,9 @@ uint32_t use_forbid_utf = forbid_utf; PCRE2_SIZE patlen, full_patlen; PCRE2_SIZE valgrind_access_length; PCRE2_SIZE erroroffset; +int32_t serialize_rc; +uint8_t *serialized_bytes; +PCRE2_SIZE serialized_size; /* The perltest.sh script supports only / as a delimiter. */ @@ -2966,6 +2969,28 @@ if ((pat_patctl.control2 & CTL2_NL_SET) != 0) rc = show_pattern_info(); if (rc != PR_OK) return rc; +/* Verify that the compiled structure can be serialized without generating +memory errors. */ + +serialize_rc = pcre2_serialize_encode((const pcre2_code **)&compiled_code, 1, + &serialized_bytes, &serialized_size, general_context); +if (serialize_rc != 1) + { + cfprintf(clr_test_error, outfile, "** pcre2_serialize_encode() returned %d instead of 1\n", + serialize_rc); + return PR_ABEND; + } + +#if defined SUPPORT_VALGRIND +if (VALGRIND_CHECK_MEM_IS_DEFINED(serialized_bytes, serialized_size) != 0) + { + cfprintf(clr_test_error, outfile, "** pcre2_serialize_encode() returned undefined data\n"); + return PR_ABEND; + } +#endif + +pcre2_serialize_free(serialized_bytes); + /* The "push" control requests that the compiled pattern be remembered on a stack. This is mainly for testing the serialization functionality. */