Hi,
Please find in attach a patch to add the malloc and alloc_size
attributes to PCRE's custom allocation functions.
The malloc attribute specifies that a given function behaves like
malloc, and therefore the returned pointer is fresh (i.e., doesn't
alias anything else). It is used mostly for optimization purposes. (I
didn't add it to the function pointers, because GCC doesn't support
that, although clang does).
The alloc_size attribute specifies that a function allocates memory of
size given by the set of specified parameters. In PCRE's case, it's
only the first parameter. This attribute enables some optimizations
and analysis of buffer overflows and related stuff.
Regards,
Nuno
Index: pcre.h.in
===================================================================
--- pcre.h.in (revision 970)
+++ pcre.h.in (working copy)
@@ -46,6 +46,11 @@
#define PCRE_PRERELEASE @PCRE_PRERELEASE@
#define PCRE_DATE @PCRE_DATE@
+/* Compatibility with non-clang compilers */
+#ifndef __has_attribute
+# define __has_attribute(x) 0
+#endif
+
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE, the appropriate
export setting is defined in pcre_internal.h, which includes this file. So we
@@ -84,6 +89,18 @@
# endif
#endif
+#if defined(__GNUC__) && __GNUC__ >= 3
+# define PCRE_ATTR_MALLOC __attribute__((__malloc__))
+#else
+# define PCRE_ATTR_MALLOC
+#endif
+
+#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || __has_attribute(alloc_size)
+# define PCRE_ATTR_ALLOC_SIZE(X) __attribute__ ((alloc_size(X)))
+#else
+# define PCRE_ATTR_ALLOC_SIZE(X)
+#endif
+
/* Have to include stdlib.h in order to ensure that size_t is defined;
it is needed here for malloc. */
@@ -386,27 +403,27 @@
have to take another form. */
#ifndef VPCOMPAT
-PCRE_EXP_DECL void *(*pcre_malloc)(size_t);
+PCRE_EXP_DECL void *(*pcre_malloc)(size_t) PCRE_ATTR_ALLOC_SIZE(1);
PCRE_EXP_DECL void (*pcre_free)(void *);
-PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t);
+PCRE_EXP_DECL void *(*pcre_stack_malloc)(size_t) PCRE_ATTR_ALLOC_SIZE(1);
PCRE_EXP_DECL void (*pcre_stack_free)(void *);
PCRE_EXP_DECL int (*pcre_callout)(pcre_callout_block *);
-PCRE_EXP_DECL void *(*pcre16_malloc)(size_t);
+PCRE_EXP_DECL void *(*pcre16_malloc)(size_t) PCRE_ATTR_ALLOC_SIZE(1);
PCRE_EXP_DECL void (*pcre16_free)(void *);
-PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t);
+PCRE_EXP_DECL void *(*pcre16_stack_malloc)(size_t) PCRE_ATTR_ALLOC_SIZE(1);
PCRE_EXP_DECL void (*pcre16_stack_free)(void *);
PCRE_EXP_DECL int (*pcre16_callout)(pcre16_callout_block *);
#else /* VPCOMPAT */
-PCRE_EXP_DECL void *pcre_malloc(size_t);
+PCRE_EXP_DECL void *pcre_malloc(size_t) PCRE_ATTR_MALLOC PCRE_ATTR_ALLOC_SIZE(1);
PCRE_EXP_DECL void pcre_free(void *);
-PCRE_EXP_DECL void *pcre_stack_malloc(size_t);
+PCRE_EXP_DECL void *pcre_stack_malloc(size_t) PCRE_ATTR_MALLOC PCRE_ATTR_ALLOC_SIZE(1);
PCRE_EXP_DECL void pcre_stack_free(void *);
PCRE_EXP_DECL int pcre_callout(pcre_callout_block *);
-PCRE_EXP_DECL void *pcre16_malloc(size_t);
+PCRE_EXP_DECL void *pcre16_malloc(size_t) PCRE_ATTR_MALLOC PCRE_ATTR_ALLOC_SIZE(1);
PCRE_EXP_DECL void pcre16_free(void *);
-PCRE_EXP_DECL void *pcre16_stack_malloc(size_t);
+PCRE_EXP_DECL void *pcre16_stack_malloc(size_t) PCRE_ATTR_MALLOC PCRE_ATTR_ALLOC_SIZE(1);
PCRE_EXP_DECL void pcre16_stack_free(void *);
PCRE_EXP_DECL int pcre16_callout(pcre16_callout_block *);
#endif /* VPCOMPAT */