[Bug analyzer/105948] RFE: analyzer could check c++ placement-new sizes

2023-09-01 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105948

--- Comment #3 from Benjamin Priour  ---
I believe the above patch resolves this PR.
I'm letting it sip in trunk for a few days before marking it as solved.

[Bug analyzer/111266] New: Missing -Wanalyzer-out-of-bounds for concrete offset overwrite.

2023-09-01 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111266

Bug ID: 111266
   Summary: Missing -Wanalyzer-out-of-bounds for concrete offset
overwrite.
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: analyzer
  Assignee: dmalcolm at gcc dot gnu.org
  Reporter: vultkayn at gcc dot gnu.org
  Target Milestone: ---

Hi,

The analyzer do not emit the expected "heap-based write overflow" in the
reproducer below.

#include 
void *malloc (__SIZE_TYPE__);
void free (void *);

void test_binop2 ()
{
  char *p = (char *) malloc (4);
  int32_t *i = (int32_t *) (p + 3);
  *i = 20042; /* { dg-warning "heap-based buffer overflow" "" { xfail *-*-* } }
*/
  free (p);
}


A quick investigation showed that on *i = 20042, check_region_bounds had the
following:

reg is an offset_region(heap_allocated(12), 'int32_', 3) as expected
base_reg is heap_allocated(12)
base_reg's capacity is correct too, and reg_offset *is* 3 bytes, as it should.

The issue comes from num_bytes_sval, which corresponds to the number of bytes
accessed. It should be a constant_svalue of value 4, but is instead of value 1.

Therefore the "read_bytes" byte_range do not overflow the buffer, as we get
(offset) 3 + (accessed bytes) 1 = 4, which is not an overflow (3 + 4 expected)

[Bug analyzer/110543] RFE: Add optional trim of the analyzer diagnostics through system headers.

2023-08-14 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110543

Benjamin Priour  changed:

   What|Removed |Added

 Resolution|--- |FIXED
 Status|UNCONFIRMED |RESOLVED

--- Comment #2 from Benjamin Priour  ---
Fixed by the above patch

[Bug analyzer/110907] New: ICE when using -fanalyzer-verbose-state-changes

2023-08-04 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110907

Bug ID: 110907
   Summary: ICE when using -fanalyzer-verbose-state-changes
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: analyzer
  Assignee: dmalcolm at gcc dot gnu.org
  Reporter: vultkayn at gcc dot gnu.org
  Target Milestone: ---

Running the analyzer on testcase gcc.dg/analyzer/pr99193-1.c with line 54
commented out and flag -fanalyzer-verbose-state-changes results in an ICE on
gcc versions later than 13.1 (included) and trunk, tested on target
x86_64-linux-gnu.

x86_64 12.3 on godbolt doesn't reproduce the ICE.

Reproducer:

/* { dg-additional-options "-Wno-analyzer-too-complex" } */

/* Verify absence of false positive from -Wanalyzer-mismatching-deallocation
   on realloc(3).
   Based on
https://github.com/libguestfs/libguestfs/blob/f19fd566f6387ce7e4d82409528c9dde374d25e0/daemon/command.c#L115
   which is GPLv2 or later.  */

typedef __SIZE_TYPE__ size_t;
typedef __builtin_va_list va_list;

#define NULL ((void *)0)

extern void *malloc (size_t __size)
  __attribute__ ((__nothrow__ , __leaf__))
  __attribute__ ((__malloc__))
  __attribute__ ((__alloc_size__ (1)));
extern void perror (const char *__s);
extern void *realloc (void *__ptr, size_t __size)
  __attribute__ ((__nothrow__ , __leaf__))
  __attribute__ ((__warn_unused_result__))
  __attribute__ ((__alloc_size__ (2)));

extern void guestfs_int_cleanup_free (void *ptr);
extern int commandrvf (char **stdoutput, char **stderror, unsigned flags,
   char const* const *argv);
#define CLEANUP_FREE __attribute__((cleanup(guestfs_int_cleanup_free))) 

int
commandrf (char **stdoutput, char **stderror, unsigned flags,
   const char *name, ...)
{
  va_list args;
  CLEANUP_FREE const char **argv = NULL;
  char *s;
  int i, r;

  /* Collect the command line arguments into an array. */
  i = 2;
  argv = malloc (sizeof (char *) * i);

 if (argv == NULL) {
perror ("malloc");
return -1;
  }
  argv[0] = (char *) name;
  argv[1] = NULL;

  __builtin_va_start (args, name);

  while ((s = __builtin_va_arg (args, char *)) != NULL) {
const char **p = realloc (argv, sizeof (char *) * (++i)); /* { dg-bogus
"'free'" } */
if (p == NULL) {
  perror ("realloc");
  // __builtin_va_end (args);
  return -1;
}
argv = p;
argv[i-2] = s;
argv[i-1] = NULL;
  }

  __builtin_va_end (args);

  r = commandrvf (stdoutput, stderror, flags, argv);

  return r;
}

-

gcc -fanalyzer -fanalyzer-verbose-state-changes ./pr99193-1.leak.c
during IPA pass: analyzer
:33:29: internal compiler error: Segmentation fault
   33 |   CLEANUP_FREE const char **argv = NULL;
  | ^~~~
0x216ac2e internal_error(char const*, ...)
???:0
0x218afec pp_format(pretty_printer*, text_info*)
???:0
0x1f7bfb6 make_label_text(bool, char const*, ...)
???:0
0x1f88b0d ana::state_change_event::get_desc(bool) const
???:0
0x1f86c0c ana::checker_event::prepare_for_emission(ana::checker_path*,
ana::pending_diagnostic*, diagnostic_event_id_t)
???:0
0x1fa79f5 ana::diagnostic_manager::emit_saved_diagnostic(ana::exploded_graph
const&, ana::saved_diagnostic const&)
???:0
0x1fa82a0 ana::diagnostic_manager::emit_saved_diagnostics(ana::exploded_graph
const&)
???:0
0x149fc31 ana::impl_run_checkers(ana::logger*)
???:0
0x14a0bdf ana::run_checkers()
???:0
Please submit a full bug report, with preprocessed source (by using
-freport-bug).
Please include the complete backtrace with any bug report.
See  for instructions.
Compiler returned: 1

[Bug analyzer/110830] New: -Wanalyzer-use-of-uninitialized-value false negative due to use-after-free::supercedes_p.

2023-07-27 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110830

Bug ID: 110830
   Summary: -Wanalyzer-use-of-uninitialized-value false negative
due to use-after-free::supercedes_p.
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: analyzer
  Assignee: dmalcolm at gcc dot gnu.org
  Reporter: vultkayn at gcc dot gnu.org
  Target Milestone: ---

state_machine::supercedes_p is called when two diagnostics are emitted for the
same statement, without regarding the path that led to this statement.
See reproducer on trunk https://godbolt.org/z/GqebW5s5h 

#include 

extern int ext();

int* foo()
{
  int *p = 0;
  if (ext() > 5)
  {
p = malloc (sizeof(int));
*p = 0;
free (p);
return p;
  }
  else
return malloc(sizeof(int));
}

void test()
{
  int *y = foo(); // (*)
  int x = 4 + *y;
  free (y);
}

At statement (*) both -Wanalyzer-use-of-uninitialized-value and
-Wanalyzer-use-after-free should be emitted as solving the latter won't impact
the former, since they result from two independent branches. But
use_after_free::supercedes_p hides the other.

In the case of a false positive -Wanalyzer-use-after-free, or simply one
ignored by the user, the adjacent -Wanalyzer-use-of-uninitialized-value would
therefore never be emitted.

[Bug analyzer/109365] Double delete yields -Wanalyzer-use-after-free instead of -Wanalyzer-double-free

2023-07-26 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109365

--- Comment #6 from Benjamin Priour  ---
(In reply to David Malcolm from comment #5)
> (In reply to Benjamin Priour from comment #4)
> > (In reply to Benjamin Priour from comment #3)
> 
> Here's a link to the reproducer:
>   https://godbolt.org/z/Wa3fqjrTK
> with the fields renamed to avoid reusing the name "a".
> 
> 
> > [...snip...]
> > > 
> > > 
> > >:
> > >   *a.0_11 ={v} {CLOBBER};
> > >   operator delete (a.0_11, 8);
> > >
> > [...snip...] 
> > >
> > > Entry statement of bb3 is the one actually detected as
> > > -Wanalyzer-double-free.
> > 
> > Given the above IPA, we cannot just ignore the assignment statement, as it
> > could really be an injurious statement, not just a pre-deallocation
> > statement at it is now.
> 
> Ths assignment statement:
>   *a.0_11 ={v} {CLOBBER};
> is a "clobber", which is a special-case of assignment, generated by the
> frontends when something is going out of scope, or becoming invalid.
> 
> We could potentially just special-case such ass
> 

Wouldn't considering "clobber" as a trigger for double-delete also lead to many
false positives ?
I'm not yet 100% familiar with and when this "clobber" appears.

[...snip...]

> > 
> > struct A
> > {
> >   ...
> >   ~A() {}
> > }
> > 
> > ...
> > 
> >  :
> >   A::~A (a.0_12);
> >   operator delete (a.0_12, 8);
> >  
> > 
> > The warnings stay the same, though it is now more reliable to check for a
> > destructor call, instead any random single assignment.
> 
> There's a sense in which it does make sense to complain about
> use-after-delete in the destructor (when the destructor is non-empty): the
> memory is being accessed after deletion.  Maybe this case would make more
> sense to the user?  (albeit being rather verbose)

I believe in the case of a non-empty destructor, "double-delete" would be more
on point than "use-after-delete", as ultimately the issue is the second call to
delete. "double-delete" immediately warns about the actual issue, whereas if
the first "delete" is not as obvious as in the above test case, a
"use-after-delete" might confuse the user.

"use-after-delete" could mislead the user to believe there is something wrong
with their destructor, although only their double delete is.

[Bug analyzer/109432] [meta-bug] tracker bug for issues with -Wanalyzer-out-of-bounds

2023-07-07 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109432
Bug 109432 depends on bug 109439, which changed state.

Bug 109439 Summary: RFE: Spurious -Wanalyzer-use-of-uninitialized-value tagging 
along -Wanalyzer-out-of-bounds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109439

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |FIXED

[Bug analyzer/109439] RFE: Spurious -Wanalyzer-use-of-uninitialized-value tagging along -Wanalyzer-out-of-bounds

2023-07-07 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109439

Benjamin Priour  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |FIXED

--- Comment #3 from Benjamin Priour  ---
Resolved as part of the above patch.

[Bug analyzer/109365] Double delete yields -Wanalyzer-use-after-free instead of -Wanalyzer-double-free

2023-07-07 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109365

Benjamin Priour  changed:

   What|Removed |Added

   Assignee|dmalcolm at gcc dot gnu.org|vultkayn at gcc dot 
gnu.org

--- Comment #4 from Benjamin Priour  ---
(In reply to Benjamin Priour from comment #3)
[...snip...]
> 
> 
>:
>   *a.0_11 ={v} {CLOBBER};
>   operator delete (a.0_11, 8);
>
[...snip...] 
>
> Entry statement of bb3 is the one actually detected as
> -Wanalyzer-double-free.

Given the above IPA, we cannot just ignore the assignment statement, as it
could really be an injurious statement, not just a pre-deallocation statement
at it is now.

Consider the code:
  A* a;
  ...
  delete a;
  a->x = 7; // (1)
  operator delete (a); (2)  

On my box, (1) and (2) generated the IPA
 :
  a_10->a = 7;
  operator delete (a_10);

Thus, I'd first only consider types where a destructor is provided (by the user
or generated).
Indeed, when a destructor is supplied for a type,  becomes something akin
to :

struct A
{
  ...
  ~A() {}
}

...

 :
  A::~A (a.0_12);
  operator delete (a.0_12, 8);


The warnings stay the same, though it is now more reliable to check for a
destructor call, instead any random single assignment. I'm considering adding a
new state to sm-malloc, RS_DESTROYED, that would also help flag use after
standalone destruction (without a succeeding deallocation).

[Bug analyzer/110578] New: Support dynamic_cast within the analyzer

2023-07-06 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110578

Bug ID: 110578
   Summary: Support dynamic_cast within the analyzer
   Product: gcc
   Version: 14.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: analyzer
  Assignee: dmalcolm at gcc dot gnu.org
  Reporter: vultkayn at gcc dot gnu.org
  Target Milestone: ---

Created attachment 55491
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55491=edit
First draft of a test case for dynamic_cast

In the attached file you will find a first draft of test cases toward
supporting dynamic_cast in the analyzer. We [the analyzer] have already gained
RTTI capabilities thanks to PR97114, so supporting dynamic_cast no longer feels
that far away.
Test cases currently failing have been marked 'xfail'.

I didn't add any test case about dynamic_cast failure given reference to types,
but rather stuck to pointers, since we don't support exceptions whatsoever.

  "If the cast fails and target-type is a reference type, it throws an
exception
   that matches a handler of type std::bad_cast."

  https://en.cppreference.com/w/cpp/language/dynamic_cast

What are your thoughts on these tests ? Do they feel complete enough for a
first implementation
of dynamic_cast into the analyzer ?

[Bug analyzer/109365] Double delete yields -Wanalyzer-use-after-free instead of -Wanalyzer-double-free

2023-07-05 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109365

Benjamin Priour  changed:

   What|Removed |Added

 CC||vultkayn at gcc dot gnu.org

--- Comment #3 from Benjamin Priour  ---
Changing the second delete expression into a direct call to "operator delete"
results in the correct warning Wanalyzer-double-free being emitted.

This is due to delete expression first calling the destructor and performing
extra operations, whose one of them is a dereference.

"delete expression" compiled with -O0 results on my x86_64-linux-gnu
to analyzer ipa:

  if (a.0_11 != 0B)
goto ; [INV]
  else
goto ; [INV]

   :
  *a.0_11 ={v} {CLOBBER};
  operator delete (a.0_11, 8);

   :
  _14 = 0;

Entry statement of bb3 is the one actually detected as -Wanalyzer-double-free.

[Bug analyzer/110543] New: RFE: Add optional trim of the analyzer diagnostics through system headers.

2023-07-04 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110543

Bug ID: 110543
   Summary: RFE: Add optional trim of the analyzer diagnostics
through system headers.
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: analyzer
  Assignee: dmalcolm at gcc dot gnu.org
  Reporter: vultkayn at gcc dot gnu.org
  Target Milestone: ---

See https://godbolt.org/z/sb9dM9Gqa for a reproducer on trunk.

Given an issue on std::shared_ptr<>, the analyzer emits a path that I'd like to
optionally shorten, by trimming it.
Looking at the reproducer, I believe it would be desirable the analyzer emits
similar diagnostics for smart pointers as it is for raw pointers, i.e. the
diagnostic should not dive into the standard library, but rather stop at the
faulting frame.

Thus behaves as follow, _by default_:

: In function 'int main()':
:5:8: warning: dereference of NULL 'a' [CWE-476]
[-Wanalyzer-null-dereference]
5 |   a->x = 4; /* Diagnostic would path should stop here rather than going
to shared_ptr_base.h */
  |   ~^~~
  'int main()': events 1-2
|
|4 |   std::shared_ptr a;
|  |  ^
|  |  |
|  |  (1) 'a' is NULL
|5 |   a->x = 4; /* Diagnostic path should stop here rather than going
to shared_ptr_base.h */
|  |   
|  ||
|  |(2) dereference of NULL 'a'
| 

A flag akin to -fanalyzer-trim-diagnostic-path=|std would then be
introduced to do so, with a default value of std.
Such option would be useful for future support of C++, but could be extended to
any "system header", thus also be used in C.


A slight variation would be to trim all but the last exceeding event, so that
the user would still get feedback on template deducted types.

What do you think ?

[Bug analyzer/105948] RFE: analyzer could check c++ placement-new sizes

2023-06-30 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105948

--- Comment #1 from Benjamin Priour  ---
I'm writing a patch for this, and I've got support for non symbolic bounds.
However, as I wrote my patch, a missing warning came up.
Consider the test case:

---

void var_too_short ()
{
  short s;
  long *lp = new () long; /* { dg-warning "stack-based buffer overflow" } */
  /* { dg-warning "allocated buffer size is not a multiple of the pointee's
size" "" { target *-*-* } .-1 } */
}

void static_buffer_too_short ()
{
  int n = 16;
  int buf[n];
  int *p = new (buf) int[n + 1]; /* { dg-warning "stack-based buffer overflow"
} */
  /* (+) */
}

---

In 'var_too_short', two warnings are emitted, second being from
'-Wanalyzer-allocation-size', which makes sense.

Then given the name of this warning, would it not also makes sense to emit it
at (+) in 'static_buffer_too_short' ?

Pointer 'p' is an int, and 'buf' is an array of int, so the buffer size is
indeed a multiple size of 'p'.

However, we know 'p' points to an area actually overflowing 'buf', so
-Wanalyzer-allocation-size is reasonable there.

What are your thoughts on that ?

[Bug analyzer/110198] [14 regression] g++.dg/analyzer/pr100244.C fails after r14-1632-g9589a46ddadc8b

2023-06-29 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110198

Benjamin Priour  changed:

   What|Removed |Added

 Resolution|--- |FIXED
 Status|NEW |RESOLVED

--- Comment #7 from Benjamin Priour  ---
Finally fixed as patch
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1eb90f46c16453f72dc119ba20b07053a15b452d

[Bug analyzer/94355] analyzer support for C++ new expression

2023-06-29 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94355

--- Comment #15 from Benjamin Priour  ---
(In reply to Jonathan Wakely from comment #14)
> [...snip...]
> 
> See the -fcheck-new option:
> 
>   Check that the pointer returned by "operator new" is non-null before
> attempting to modify the storage allocated.  This check is normally
> unnecessary because the C++ standard specifies that "operator new" only
> returns 0 if it is declared "throw()", in which case the compiler always
> checks the return value even without this option.  In all other cases, when
> "operator new" has a non-empty exception specification, memory exhaustion is
> signalled by throwing "std::bad_alloc".  See also new (nothrow).


Should we use the above flag's value to also optionally disable the analyzer
warnings on operator new possibly returning NULL?

Or maybe there could be an additional flag -fanalyzer-new-returns-null, turned
'on' by default.

Having such capability would be useful to run the analyzer against itself, as
GCC is built without exceptions (thus every operator new possibly returns
NULL).

[Bug analyzer/110198] [14 regression] g++.dg/analyzer/pr100244.C fails after r14-1632-g9589a46ddadc8b

2023-06-09 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110198

--- Comment #2 from Benjamin Priour  ---
Yes sorry for the regression. I confirmed it myself too on x86_64-linux-gnu.
I wrote a fix immediately yesterday, and I am currently regtesting it.

It is promising as I quickly ran the test only for the analyzer test cases, all
of them now are back to their expected behavior.

I'm sending the patch as soon as the regtesting finishes, so probably tomorrow
evening, as my keys on the compiler farm are not yet synced.

For pr101962.c, it was indeed just a now obsolete message that had to be
removed.

For pr100244.C it required to change the way OOB are handled by the
uninitialized-value checker.

[Bug analyzer/106392] Support iteration over C++ containers in -fanalyzer

2023-06-08 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106392

--- Comment #3 from Benjamin Priour  ---

> I think the unordered containers might be too hard. I would start with
> std::vector, as that will probably give the best return on investment of
> effort.
> 

Indeed, I just found these slides from clang
https://llvm.org/devmtg/2018-04/slides/Balogh-Finding%20Iterator-related%20Errors%20with%20Clang%20Static%20Analyzer.pdf

They seem to be dividing the containers into 3 categories, list-like,
vector-like and deque-like, thus also sticking to ordered containers.

But they also are kind of brute-forcing the checks it seems, as they say upon
insertion or deletion, they check every iterator position of the container.

It sounds overly expensive to me, particularly for lists.
Surely there is a reason they are doing that, I'm looking into it.

[Bug analyzer/106390] Support gsl::owner and/or [[gnu::owner]] attribute in -fanalyzer

2023-06-08 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106390

--- Comment #5 from Benjamin Priour  ---

> I agree that this would be a problem, but instead of implying that we need
> two attributes, I think this implies that we should not try to use
> [[gsl::owner]] for shared ownership. If you don't try to use it for both,
> the problem doesn't exist.

If we discard tracking shared ownership, it indeed removes a lot of complexity,
and I agree we can stick to [[gsl::owner]], and tracking moves of resources
becomes much simpler.

I'll go with that for now, see what tests I can do, dig a little bit.

[Bug analyzer/106392] Support iteration over C++ containers in -fanalyzer

2023-06-08 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106392

Benjamin Priour  changed:

   What|Removed |Added

 CC||vultkayn at gcc dot gnu.org

--- Comment #1 from Benjamin Priour  ---
Access to end iterator should be flagged as undefined behavior.
Detecting invalidation is a difficult problem, as many methods are only
sometimes invalidating.
Checking a reallocation of the underlying container, e.g. for vectors, is
(always?) a good check, but it is not sufficient, e.g. consider
unordered_map.rehash(0)

Additionally, flagging all calls to "possibly invalidating operations" will
obviously lead to too
many false positive.

Thus, it might be relevant to have multiple attributes that keep track of
different kinds of invalidation.
Invalidating operations not only differ on their certainty, but on the
iterator(s) they invalidate.
Some will invalidate every iterators, while some


[[gnu::invalidate]] - always invalidate
[[gnu::invalidate(resize[, size_varname, capacity_varname, factor_varname ])]]
- All iterators are invalidated ? Examples of such case is a vector's size
exceeding its capacity, or a hashmap too loaded.
Would be detected by keeping track of push*, emplace*, insert* methods, as
well as clear, extract, erase.
If size_, capacity_ and factor_varname are provided, the invalidation is
done only if size/capacity >= factor. 
[[gnu::invalidate(swap)]] - Both containers should be invalidated. Name
probably ill-chosen since swapping two lists invalidates nothing. 
[[gnu::invalidate(rehash)]] - Generic remapping of every key -> element. This
one I think could be entirely replaced by the following.
[[gnu::invalidate(adaptor)]] - Look at the underlying container invalidation
rule.
[[gnu::invalidate(_from_[, _to_[, _step_]])]] - Invalidate all iterators from
_from_ to _to_ (default end()), with a jump of _step_ (default 1).

Or combine them.

For adaptors, we must look at their underlying containers.

What policy to take for unknown parameters ?
Typically if the load factor is determined at runtime, we simply cannot
precisely determine the event.
I believe that in such case, either the previous known value is used by the
analyzer as a heuristic, or if no other known user-provided value was given,
we use the implementation's default value.

When invalidating a range, how to determine the "following" iterators, that
should be invalidated, when we are not dealing with random iterators ?
Is there even such a case in the standard library, where a method over a
container without random iterators invalidates a range/ a subset of all
iterators ?
I didn't find any, and it is also counter-intuitive, and std::*_list certainly
are not.

More research needed.

[Bug analyzer/106390] Support gsl::owner and/or [[gnu::owner]] attribute in -fanalyzer

2023-06-08 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106390

Benjamin Priour  changed:

   What|Removed |Added

 CC||vultkayn at gcc dot gnu.org

--- Comment #3 from Benjamin Priour  ---
I think gsl::owner might be insufficient and we should rather introduce
[[gnu::owner(unique)]] and [[gnu::owner(shared)]] 

Let's say we only had [[gnu::owner]] for ownership, whether unique or shared.
If so, annotating [[gnu::owner]] would mean "I am becoming A (not THE) owner of
the given resource", i.e. it would always mean "shared" ownership.

Yet doing so would make the attribute only useful to check spurious
deallocations of non-owned resource, as well as detect the resource has been
released in the destructor, but otherwise useless to check move operations, as
we cannot require a move upon acquiring a shared resource.

Thus an additional attribute will be necessary anyway, either to differentiate
"shared" and "unique" ownership, or to annotate a move operation. 

I believe [[gnu::owner(unique|shared)]] to be preferable, as we can use it to
deduce a move operation, whereas a flagged move does not induce the quality of
ownership.

[Bug analyzer/109432] [meta-bug] tracker bug for issues with -Wanalyzer-out-of-bounds

2023-05-20 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109432
Bug 109432 depends on bug 109437, which changed state.

Bug 109437 Summary: -Wanalyzer-out-of-bounds is emitted at most once per frame.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109437

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |DUPLICATE

[Bug analyzer/109437] -Wanalyzer-out-of-bounds is emitted at most once per frame.

2023-05-20 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109437

Benjamin Priour  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |DUPLICATE

--- Comment #2 from Benjamin Priour  ---
I mark it as fixed as my current hotfix on PR109439 proved this one was indeed
just a consequence of it, and not a standalone bug.

*** This bug has been marked as a duplicate of bug 109439 ***

[Bug analyzer/109439] RFE: Spurious -Wanalyzer-use-of-uninitialized-value tagging along -Wanalyzer-out-of-bounds

2023-05-20 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109439

--- Comment #1 from Benjamin Priour  ---
*** Bug 109437 has been marked as a duplicate of this bug. ***

[Bug analyzer/109437] -Wanalyzer-out-of-bounds is emitted at most once per frame.

2023-05-01 Thread vultkayn at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109437

Benjamin Priour  changed:

   What|Removed |Added

 CC||vultkayn at gcc dot gnu.org

--- Comment #1 from Benjamin Priour  ---
(In reply to Benjamin Priour from comment #0)
> OOB refers to Out-Of-Bounds.
> 
> Curiously, it seems that if a frame was a cause for a OOB (either by
> containing the spurious code or by being a caller to such code), it will
> only emit one set of warning, rather than at each unique compromising
> statements.
> 
> 
> int consecutive_oob_in_frame ()
> {
> int arr[] = {1,2,3,4,5,6,7};
> int y1 = arr[9]; // only  this one is diagnosed
> int y2 = arr[10]; // no OOB warning emitted here ...
> int y3 = arr[50]; // ... nor here.
> return (y1+y2+y3);
> }
> 
> int main () {
> consecutive_oob_in_frame (); // OOB warning emitted
> int x [] = {1,2};
> x[5]; /* silent, probably because another set of OOB warnings
> has already been issued with this frame being the source */
> return 0;
> }
> 
> 
> As per David suggestion, it might be worth to implement
> pending_diagnostic::supercedes_p vfunc for the OOB checker.

Actually the cause seems to be related to
[https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109439]. Indeed, the further
warning are not emitted only after an OOB read. Consider:

int arr[] = {1,2,3,4,5,6,7};
arr[9] = 7; // 1 warning OOB
arr[15] = 12; // 1 warning OOB
int y = arr[12]; // 2 Warnings as in PR109439, terminate path
arr[11]; // No warnings

The reason is because of the poisoned_value diagnostic that is implementing the
diagnostic_path::terminate_path method