void impl_call_pre (const call_details &cd) const final override
{
region_model *model = cd.get_model ();
+ region_model_context *ctxt = cd.get_ctxt ();
region_model_manager *mgr = cd.get_manager ();
- cd.check_for_null_terminated_string_arg (0);
- /* Ideally we'd get the size here, and simulate copying the bytes. */
- const region *new_reg
- = model->get_or_create_region_for_heap_alloc (NULL, cd.get_ctxt ());
- model->mark_region_as_unknown (new_reg, NULL);
- if (cd.get_lhs_type ())
+ const svalue *bytes_to_copy;
+ if (const svalue *num_bytes_read_sval
+ = cd.check_for_null_terminated_string_arg (0, true, &bytes_to_copy))
{
- const svalue *ptr_sval
- = mgr->get_ptr_svalue (cd.get_lhs_type (), new_reg);
- cd.maybe_set_lhs (ptr_sval);
+ const region *new_reg
+ = model->get_or_create_region_for_heap_alloc (num_bytes_read_sval,
+ ctxt);
+ model->write_bytes (new_reg, num_bytes_read_sval, bytes_to_copy, ctxt);
+ if (cd.get_lhs_type ())
+ {
+ const svalue *ptr_sval
+ = mgr->get_ptr_svalue (cd.get_lhs_type (), new_reg);
+ cd.maybe_set_lhs (ptr_sval);
+ }
+ }
+ else
+ {
+ if (ctxt)
+ ctxt->terminate_path ();
}
}
};
Based on https://github.com/libguestfs/libguestfs/blob/f19fd566f6387ce7e4d82409528c9dde374d25e0/df/main.c#L404
which is GPLv2 or later. */
+/* { dg-additional-options "-Wno-analyzer-too-complex" } */
+
typedef __SIZE_TYPE__ size_t;
typedef __builtin_va_list va_list;
#include <string.h>
#include <stdlib.h>
+#include "analyzer-decls.h"
+
extern void requires_nonnull (void *ptr)
__attribute__((nonnull));
return strdup (buf); /* { dg-warning "use of uninitialized value 'buf\\\[0\\\]'" } */
/* { dg-message "while looking for null terminator for argument 1 \\('&buf'\\) of 'strdup'..." "event" { target *-*-* } .-1 } */
}
+
+char *test_concrete_strlen (void)
+{
+ char *p = strdup ("abc");
+ if (!p)
+ return p;
+ __analyzer_eval (__analyzer_get_strlen (p) == 3); /* { dg-warning "TRUE" } */
+ __analyzer_eval (p[0] == 'a'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (p[1] == 'b'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (p[2] == 'c'); /* { dg-warning "TRUE" } */
+ __analyzer_eval (p[3] == '\0'); /* { dg-warning "TRUE" } */
+ return p;
+}
+
+char *test_symbolic_strlen (const char *p)
+{
+ char *q = strdup (p);
+ if (!q)
+ return q;
+ __analyzer_eval (__analyzer_get_strlen (p) == __analyzer_get_strlen (q)); /* { dg-warning "UNKNOWN" } */
+ // TODO: should be TRUE
+ __analyzer_eval (p[0] == q[0]); /* { dg-warning "UNKNOWN" } */
+ // TODO: should be TRUE
+ return q;
+}