diff --git a/ChangeLog b/ChangeLog index 21f4ccb..c0fb1ba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -155,6 +155,11 @@ bcopy() doesn't return a result. This feature is now refactored always to call an emulation function when there is no memmove(). The emulation makes use of bcopy() when available. +34. When serializing a pattern, set the memctl, executable_jit, and tables +fields (that is, all the fields that contain pointers) to zeros so that the +result of serializing is always the same. These fields are re-set when the +pattern is deserialized. + Version 10.31 12-February-2018 ------------------------------ diff --git a/src/pcre2_serialize.c b/src/pcre2_serialize.c index d2cc603..d6fdf35 100644 --- a/src/pcre2_serialize.c +++ b/src/pcre2_serialize.c @@ -127,7 +127,21 @@ dst_bytes += tables_length; for (i = 0; i < number_of_codes; i++) { re = (const pcre2_real_code *)(codes[i]); - memcpy(dst_bytes, (char *)re, re->blocksize); + (void)memcpy(dst_bytes, (char *)re, re->blocksize); + + /* Certain fields in the compiled code block are re-set during + deserialization. In order to ensure that the serialized data stream is always + the same for the same pattern, set them to zero here. We can't assume the + copy of the pattern is correctly aligned for accessing the fields as part of + a structure. */ + + (void)memset((void *)(dst_bytes + offsetof(pcre2_real_code, memctl)), 0, + sizeof(pcre2_memctl)); + (void)memset((void *)(dst_bytes + offsetof(pcre2_real_code, tables)), 0, + sizeof(uint8_t *)); + (void)memset((void *)(dst_bytes + offsetof(pcre2_real_code, executable_jit)), + 0, sizeof(void *)); + dst_bytes += re->blocksize; }