Skip to content

Gcc analyzer/v2 - #15607

Closed
victorjulien wants to merge 17 commits into
OISF:mainfrom
victorjulien:gcc-analyzer/v2
Closed

Gcc analyzer/v2#15607
victorjulien wants to merge 17 commits into
OISF:mainfrom
victorjulien:gcc-analyzer/v2

Conversation

@victorjulien

Copy link
Copy Markdown
Member

Gcc analyzer fixes and CI test.

Replaces #15559.

victorjulien and others added 17 commits June 11, 2026 13:26
To assist code analyzers. Gcc -fanalyzer got confused about it.

Also test data pointer and length before calling fwrite and check the
result better.

Use a single atomic for the max open files check.
Code analyzer flagged FrameCopy as a possible source of UB due to
both pointers passed to memcpy being the same.

app-layer-frames.c: In function ‘FrameCopy’:
app-layer-frames.c:236:5: warning: overlapping buffers passed as arguments to ‘memcpy’ [-Wanalyzer-overlapping-buffers]
  236 |     memcpy(dst, src, sizeof(*dst));
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ‘FramePrune’: events 1-8
    │
    │  750 | static void FramePrune(Frames *frames, const TcpStream *stream, const bool eof)
    │      |             ^~~~~~~~~~
    │      |             |
    │      |             (1) entry to ‘FramePrune’
    │......
    │  766 |     for (uint16_t i = 0; i < frames->cnt; i++) {
    │      |                          ~~~~~~~~~~~~~~~
    │      |                            |
    │      |                            (2) following ‘true’ branch... ─>─┐
    │      |                                                              │
    │      |                                                              │
    │      |┌─────────────────────────────────────────────────────────────┘
    │  767 |│        if (i < FRAMES_STATIC_CNT) {
    │      |│           ~
    │      |│           |
    │      |└──────────>(3) ...to here
    │      |            (4) following ‘true’ branch (when ‘i <= 2’)... ─>─┐
    │      |                                                              │
    │      |                                                              │
    │      |┌─────────────────────────────────────────────────────────────┘
    │  768 |│            Frame *frame = &frames->sframes[i];
    │      |│                            ~~~~~~~~~~~~~~~~~~
    │      |│                                           |
    │      |└──────────────────────────────────────────>(5) ...to here
    │  769 |             FrameDebug("prune(s)", frames, frame);
    │  770 |             if (eof || FrameIsDone(frame, acked)) {
    │      |                ~
    │      |                |
    │      |                (6) following ‘false’ branch... ─>─┐
    │      |                                                   │
    │......
    │      |                                                   │
    │      |┌──────────────────────────────────────────────────┘
    │  779 |│                const uint64_t fle = FrameLeftEdge(stream, frame);
    │      |│                                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    │      |│                                     |
    │      |└────────────────────────────────────>(7) ...to here
    │      |                                      (8) calling ‘FrameLeftEdge’ from ‘FramePrune’
    │
    └──> ‘FrameLeftEdge’: event 9
           │
           │  257 | static inline uint64_t FrameLeftEdge(const TcpStream *stream, const Frame *frame)
           │      |                        ^~~~~~~~~~~~~
           │      |                        |
           │      |                        (9) entry to ‘FrameLeftEdge’
           │
         ‘FrameLeftEdge’: event 10
           │
           │suricata-common.h:323:27:
           │  323 |         #define BUG_ON(x) assert(!(x))
           │      |                           ^~~~~~
           │      |                           |
           │      |                           (10) following ‘false’ branch (when ‘frame_offset <= app_progress’)... ─>─┐
           │      |                                                                                                     │
util-validate.h:95:36: note: in expansion of macro ‘BUG_ON’
           │   95 | #define DEBUG_VALIDATE_BUG_ON(exp) BUG_ON((exp))
           │      |                                    ^~~~~~
app-layer-frames.c:266:5: note: in expansion of macro ‘DEBUG_VALIDATE_BUG_ON’
           │  266 |     DEBUG_VALIDATE_BUG_ON(frame_offset > app_progress);
           │      |     ^~~~~~~~~~~~~~~~~~~~~
           │
         ‘FrameLeftEdge’: event 11
           │
           │      |                                                                                                     │
           │      |┌────────────────────────────────────────────────────────────────────────────────────────────────────┘
           │  269 |│    if (frame->len < 0) {
           │      |│        ~~~~~^~~~~
           │      |│             |
           │      |└────────────>(11) ...to here
           │
    <──────┘
    │
  ‘FramePrune’: events 12-13
    │
    │  779 |                 const uint64_t fle = FrameLeftEdge(stream, frame);
    │      |                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
    │      |                                      |
    │      |                                      (12) returning to ‘FramePrune’ from ‘FrameLeftEdge’
    │......
    │  783 |                 FrameCopy(nframe, frame);
    │      |                 ~~~~~~~~~~~~~~~~~~~~~~~~
    │      |                 |
    │      |                 (13) calling ‘FrameCopy’ from ‘FramePrune’
    │
    └──> ‘FrameCopy’: events 14-15
           │
           │  234 | static void FrameCopy(Frame *dst, Frame *src)
           │      |             ^~~~~~~~~
           │      |             |
           │      |             (14) entry to ‘FrameCopy’
           │  235 | {
           │  236 |     memcpy(dst, src, sizeof(*dst));
           │      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           │      |     |
           │      |     (15) ⚠️  overlapping buffers passed as arguments to ‘memcpy’
           │
In file included from suricata-common.h:129,
                 from app-layer-frames.c:25:
/usr/include/string.h:47:14: note: the behavior of ‘memcpy’ is undefined for overlapping buffers
   47 | extern void *memcpy (void *__restrict __dest, const void *__restrict __src,
      |              ^~~~~~
Work around TAILQ false positive.
Work around TAILQ false positive.
Addresses a gcc -fanalyzer warning.
Add debug validation statement to assert prev pointer is not NULL.
Helps address a gcc -fanalyzer warning.
Reopen file descriptor for lz4 with the init function. This helps
code analyzers understand the handle it's leaked.

Improve flow of profiling dumps to avoid analyzer confusion around the
file descriptor.

Suppress TAILQ related warnings.
By teaching about TAILQ.
The double strchr confused gcc -fanalyzer.
Avoids gcc -fanalyzer warning about out of bounds write to the array.
Help it understand TAILQ.
Pointer can't be NULL, so don't check it.

Helps gcc analyzer as well.
Make sure to not run against lua rust crate build, as it's not clean.
@victorjulien
victorjulien requested review from a team and jasonish as code owners June 11, 2026 11:35
@victorjulien victorjulien mentioned this pull request Jun 11, 2026
@codecov

codecov Bot commented Jun 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.25197% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.88%. Comparing base (d154484) to head (6cf61ec).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #15607      +/-   ##
==========================================
- Coverage   82.89%   82.88%   -0.02%     
==========================================
  Files        1006     1006              
  Lines      273487   273526      +39     
==========================================
- Hits       226710   226701       -9     
- Misses      46777    46825      +48     
Flag Coverage Δ
fuzzcorpus 61.40% <65.62%> (-0.01%) ⬇️
livemode 18.51% <11.45%> (+0.03%) ⬆️
netns 22.78% <16.16%> (+<0.01%) ⬆️
pcap 45.14% <33.33%> (-0.08%) ⬇️
suricata-verify 66.63% <76.41%> (-0.03%) ⬇️
unittests 58.52% <45.61%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@suricata-qa

Copy link
Copy Markdown

WARNING:

field baseline test %
SURI_TLPW2_single_stats_chk
.decoder.event.sctp.chunk_too_small - 0 -
.decoder.event.sctp.chunk_len_invalid - 0 -
.decoder.event.sctp.init_chunk_bundled - 0 -
.decoder.event.sctp.init_with_non_zero_vtag - 0 -
.decoder.event.sctp.data_with_zero_vtag - 0 -
.decoder.event.sctp.too_many_chunks - 0 -
.decoder.event.sctp.too_many_data_chunks - 0 -
.sctp.init - 0 -
.sctp.init_ack - 0 -
.sctp.data - 0 -
.sctp.abort - 0 -
.sctp.shutdown - 0 -
SURI_TLPW2_autofp_stats_chk
.decoder.event.sctp.chunk_too_small - 0 -
.decoder.event.sctp.chunk_len_invalid - 0 -
.decoder.event.sctp.init_chunk_bundled - 0 -
.decoder.event.sctp.init_with_non_zero_vtag - 0 -
.decoder.event.sctp.data_with_zero_vtag - 0 -
.decoder.event.sctp.too_many_chunks - 0 -
.decoder.event.sctp.too_many_data_chunks - 0 -
.sctp.init - 0 -
.sctp.init_ack - 0 -
.sctp.data - 0 -
.sctp.abort - 0 -
.sctp.shutdown - 0 -
SURI_TLPW1_stats_chk
.decoder.event.sctp.chunk_too_small - 0 -
.decoder.event.sctp.chunk_len_invalid - 0 -
.decoder.event.sctp.init_chunk_bundled - 0 -
.decoder.event.sctp.init_with_non_zero_vtag - 0 -
.decoder.event.sctp.data_with_zero_vtag - 0 -
.decoder.event.sctp.too_many_chunks - 0 -
.decoder.event.sctp.too_many_data_chunks - 0 -
.sctp.init - 0 -
.sctp.init_ack - 0 -
.sctp.data - 0 -
.sctp.abort - 0 -
.sctp.shutdown - 0 -
SURI_TLPR1_stats_chk
.decoder.event.sctp.chunk_too_small - 0 -
.decoder.event.sctp.chunk_len_invalid - 0 -
.decoder.event.sctp.init_chunk_bundled - 0 -
.decoder.event.sctp.init_with_non_zero_vtag - 0 -
.decoder.event.sctp.data_with_zero_vtag - 0 -
.decoder.event.sctp.too_many_chunks - 0 -
.decoder.event.sctp.too_many_data_chunks - 0 -
.sctp.init - 0 -
.sctp.init_ack - 0 -
.sctp.data - 0 -
.sctp.abort - 0 -
.sctp.shutdown - 0 -
IPS_AFP_stats_chk
.decoder.event.sctp.chunk_too_small - 0 -
.decoder.event.sctp.chunk_len_invalid - 0 -
.decoder.event.sctp.init_chunk_bundled - 0 -
.decoder.event.sctp.init_with_non_zero_vtag - 0 -
.decoder.event.sctp.data_with_zero_vtag - 0 -
.decoder.event.sctp.too_many_chunks - 0 -
.decoder.event.sctp.too_many_data_chunks - 0 -
.sctp.init - 0 -
.sctp.init_ack - 0 -
.sctp.data - 0 -
.sctp.abort - 0 -
.sctp.shutdown - 0 -
TREX_GENERIC_stats_chk
.decoder.event.sctp.chunk_too_small - 0 -
.decoder.event.sctp.chunk_len_invalid - 0 -
.decoder.event.sctp.init_chunk_bundled - 0 -
.decoder.event.sctp.init_with_non_zero_vtag - 0 -
.decoder.event.sctp.data_with_zero_vtag - 0 -
.decoder.event.sctp.too_many_chunks - 0 -
.decoder.event.sctp.too_many_data_chunks - 0 -
.sctp.init - 0 -
.sctp.init_ack - 0 -
.sctp.data - 0 -
.sctp.abort - 0 -
.sctp.shutdown - 0 -

Pipeline = 31963

@jufajardini jufajardini left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. suri-review only pointed out that one of the commits could indicate that there's also a bug fix, but that's it.

@victorjulien victorjulien added this to the 9.0 milestone Jun 11, 2026
Comment thread src/output-filestore.c
Comment on lines +225 to 234
/* SC_ATOMIC_ADD returns value before the addition. */
if (FileGetMaxOpenFiles() > 0 &&
SC_ATOMIC_ADD(filestore_open_file_cnt, 1) >= FileGetMaxOpenFiles()) {
(void)SC_ATOMIC_SUB(filestore_open_file_cnt, 1);
StatsCounterIncr(&tv->stats, aft->counter_max_hits);
ff->fd = -1;
close_file = true; /* not storing it, so need to close */
} else {
ff->fd = file_fd;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an issue here. The default FileGetMaxOpenFiles() is 0, which means we immediately close so we're not holding onto any file descriptors. With this change, 0 is unbounded and we can easily go over the number of open file descriptors allowed by the process.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Addressed in #15612

@victorjulien

Copy link
Copy Markdown
Member Author

Looks good to me. suri-review only pointed out that one of the commits could indicate that there's also a bug fix, but that's it.

Now I'm extra curious about this somewhat vague approval. What was the bugfix?

@victorjulien victorjulien mentioned this pull request Jun 11, 2026
@victorjulien

Copy link
Copy Markdown
Member Author

replaced by #15612

@jufajardini

Copy link
Copy Markdown
Contributor

Looks good to me. suri-review only pointed out that one of the commits could indicate that there's also a bug fix, but that's it.

Now I'm extra curious about this somewhat vague approval. What was the bugfix?

It was for this commit: 4f681f2 It said that the args[1] usage was a bug fix, because the str_ptr could be used after free.

@victorjulien

Copy link
Copy Markdown
Member Author

Looks good to me. suri-review only pointed out that one of the commits could indicate that there's also a bug fix, but that's it.

Now I'm extra curious about this somewhat vague approval. What was the bugfix?

It was for this commit: 4f681f2 It said that the args[1] usage was a bug fix, because the str_ptr could be used after free.

That was the complaint by gcc as well, but I think it was a FP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

5 participants