|| is_std_named_call_p (callee_fndecl, "malloc", call, 1)
|| is_std_named_call_p (callee_fndecl, "calloc", call, 2)
|| is_named_call_p (callee_fndecl, "__builtin_malloc", call, 1)
- || is_named_call_p (callee_fndecl, "__builtin_calloc", call, 2))
+ || is_named_call_p (callee_fndecl, "__builtin_calloc", call, 2)
+ || is_named_call_p (callee_fndecl, "strdup", call, 1)
+ || is_named_call_p (callee_fndecl, "strndup", call, 2))
{
on_allocator_call (sm_ctxt, call, m_malloc);
return true;
--- /dev/null
+#include <string.h>
+#include <stdlib.h>
+
+extern void requires_nonnull (void *ptr)
+ __attribute__((nonnull));
+
+void test_1 (const char *s)
+{
+ char *p = strdup (s); /* { dg-message "allocated here" } */
+} /* { dg-warning "leak of 'p'" } */
+
+void test_2 (const char *s)
+{
+ char *p = strdup (s);
+ free (p);
+}
+void test_3 (const char *s)
+{
+ char *p = strdup (s); /* { dg-message "this call could return NULL" } */
+ requires_nonnull (p); /* { dg-warning "use of possibly-NULL 'p'" } */
+}
--- /dev/null
+#include <string.h>
+#include <stdlib.h>
+
+extern void requires_nonnull (void *ptr)
+ __attribute__((nonnull));
+
+void test_1 (const char *s)
+{
+ char *p = strndup (s, 42); /* { dg-message "allocated here" } */
+} /* { dg-warning "leak of 'p'" } */
+
+void test_2 (const char *s)
+{
+ char *p = strndup (s, 42);
+ free (p);
+}
+void test_3 (const char *s)
+{
+ char *p = strndup (s, 42); /* { dg-message "this call could return NULL" } */
+ requires_nonnull (p); /* { dg-warning "use of possibly-NULL 'p'" } */
+}