Skip to content

greptile: Reduce ruleset to memory-allocation, logging-api, and string-safety #240

Merged
suphawitwanl merged 3 commits intomasterfrom
greptile-first-roll-out-3
Apr 28, 2026
Merged

greptile: Reduce ruleset to memory-allocation, logging-api, and string-safety #240
suphawitwanl merged 3 commits intomasterfrom
greptile-first-roll-out-3

Conversation

@yutanaofficial
Copy link
Copy Markdown

Settings:

  • Strictness 2, status check enabled, re-reviews on every push
  • Comment types: logic, syntax, style

Rule structure:
Each rule has an id, description, scope, and severity.

  • Scope: glob patterns that limit which files the rule applies to (all three rules scope to **/.c, **/.h, **/*.cpp)
  • Severity: critical (P0 — must fix), high (P1 — should fix), medium (P2 — consider fix)

Rules cover:

  • Memory safety: XMALLOC/XCALLOC/XREALLOC/XSTRDUP/XFREE enforcement, no raw malloc/calloc/realloc/free, MTYPE tracking via DECLARE_MTYPE/DEFINE_MTYPE, prefer DEFINE_MTYPE_STATIC for module-private types
  • String safety: no strcpy/strcat/sprintf, enforce strlcpy/strlcat/snprintf, buffer size arguments must use sizeof()
  • Logging: zlog_* (zlog_debug, zlog_err, zlog_warn, zlog_info, zlog_notice) and flog_/flog_err_sys (structured error logging with EC_ codes), no printf/stdio, all debug statements guarded by CLI-controllable debug flags

Doc context loaded by Greptile (.greptile/files.json):

  • doc/developer/workflow.rst — coding standards, string-safety policy, debug-guard requirement
  • doc/developer/memtypes.rst — XMALLOC/MTYPE system reference
  • doc/developer/logging.rst — zlog/flog API, debug message conventions

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 28, 2026

Greptile Summary

This PR introduces a Greptile configuration for FRR that enforces three coding rules (memory-allocation, logging-api, string-safety) scoped to C/C++ source files. The context loading (files.json) is correct, but the rule definitions have a meaningful coverage gap.

  • strdup()/strndup() not in the memory-allocation ban: both perform raw heap allocation without MTYPE tracking — functionally equivalent to bare malloc — yet neither appears in the banned-function list. Multiple .c files in the repo actively use strdup(), so this gap would silently pass the most common MTYPE-bypass pattern.
  • vsprintf absent from string-safety: the rule bans sprintf but not vsprintf, which is identically unsafe and trivially substitutable.

Confidence Score: 4/5

Safe to merge after closing the strdup/strndup gap in the memory-allocation rule; the config is otherwise well-structured.

One P1 finding: strdup/strndup are missing from the memory-allocation ban list, meaning MTYPE-bypassing string duplication will go unflagged by automated review. The remaining findings (missing vsprintf, snprintfrr guidance) are P2 style improvements that don't block enforcement correctness.

.greptile/config.json — the memory-allocation and string-safety rule text needs strdup/strndup and vsprintf added to their respective ban lists.

Important Files Changed

Filename Overview
.greptile/config.json Introduces three enforcement rules (memory-allocation, logging-api, string-safety); the memory-allocation rule omits strdup/strndup from its banned-function list, leaving a real MTYPE-bypass vector unguarded, and the string-safety rule is missing vsprintf from its prohibition.
.greptile/files.json Loads three FRR developer docs as context (workflow.rst, memtypes.rst, logging.rst); content and descriptions are accurate and complete.
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
.greptile/config.json:26-29
**`strdup`/`strndup` not banned, leaving a MTYPE-bypass vector open**

The memory-allocation rule explicitly bans `malloc`, `calloc`, `realloc`, and `free` but silently omits `strdup()` and `strndup()`. Both perform a raw heap allocation with no MTYPE tracking — they are functionally equivalent to `malloc` + `strcpy` from the memory-accounting perspective. The codebase already contains multiple `.c` files using bare `strdup()` (confirmed via search), which is exactly the pattern this ruleset is supposed to catch and flag. The correct FRR replacement (`XSTRDUP(MTYPE_*, ...)`) is already named in the rule text, so the missing piece is simply declaring the banned side:

```
"NEVER allow standard malloc(), calloc(), realloc(), strdup(), strndup(), or free(). ..."
```

Without this addition, `strdup()` calls will pass automated review silently.

### Issue 2 of 3
.greptile/config.json:37-42
**`vsprintf` missing from string-safety ban list**

The string-safety rule bans `sprintf()` but says nothing about `vsprintf()`. The two functions are identically unsafe — neither performs bounds checking — and any `sprintf` ban is trivially circumvented by wrapping the call with a `va_list` argument. The FRR codebase already uses `vsnprintf` (the safe form) in multiple files, confirming that va_list-based string formatting is common enough to warrant explicit coverage. Add `vsprintf()` to the forbidden list alongside `sprintf()` and pair it with `vsnprintf()` as the enforcement target.

### Issue 3 of 3
.greptile/config.json:37-42
**`snprintfrr` omitted as preferred alternative to `snprintf`**

The string-safety rule enforces `snprintf` as the replacement for `sprintf`, but FRR's own logging infrastructure (`logging.rst`) defines `snprintfrr`/`vsnprintfrr` as the preferred formatting functions when printing FRR-specific types using format extensions (`%pFX`, `%pI4`, `%pSU`, etc.). A rule that only names `snprintf` as the target gives no guidance on when to prefer `snprintfrr`, which means reviewers may accept code using plain `snprintf` in contexts that require FRR format extensions, silently producing `%p`-style literal output instead of the intended address. Consider noting that `snprintfrr` (and its variants) should be preferred over `snprintf` when FRR-specific format specifiers are involved.

Reviews (2): Last reviewed commit: "greptile: Fix invalid commentTypes value..." | Re-trigger Greptile

Comment thread .greptile/config.json
Comment on lines +27 to +29
"rule": "NEVER allow standard malloc(), calloc(), realloc(), or free(). Enforce FRR's XCALLOC, XMALLOC, XREALLOC, XSTRDUP, and XFREE macros (requires MTYPE). Every allocation must use the MTYPE tracking system declared via DECLARE_MTYPE/DEFINE_MTYPE. Prefer DEFINE_MTYPE_STATIC for module-private types.",
"scope": ["**/*.c", "**/*.h", "**/*.cpp"],
"severity": "critical"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 critical severity applied to a "Prefer" recommendation

The memory-allocation rule mixes a hard, mandatory ban with a soft preference under the same critical severity. Automated enforcement will treat any violation of the entire rule text as a P0 blocker — meaning a contributor who writes DEFINE_MTYPE(...) instead of DEFINE_MTYPE_STATIC(...) for a module-private type will receive a critical/must-fix flag, even though the guideline explicitly says "Prefer" (not "Require"). Either split this into two rules with different severities, or promote the DEFINE_MTYPE_STATIC preference to a separate medium-severity rule so reviewers can distinguish genuine memory-safety violations from style guidance.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .greptile/config.json
Line: 27-29

Comment:
**`critical` severity applied to a "Prefer" recommendation**

The `memory-allocation` rule mixes a hard, mandatory ban with a soft preference under the same `critical` severity. Automated enforcement will treat _any_ violation of the entire rule text as a P0 blocker — meaning a contributor who writes `DEFINE_MTYPE(...)` instead of `DEFINE_MTYPE_STATIC(...)` for a module-private type will receive a critical/must-fix flag, even though the guideline explicitly says "Prefer" (not "Require"). Either split this into two rules with different severities, or promote the `DEFINE_MTYPE_STATIC` preference to a separate `medium`-severity rule so reviewers can distinguish genuine memory-safety violations from style guidance.

How can I resolve this? If you propose a fix, please make it concise.

Comment thread .greptile/config.json
Comment on lines +32 to +35
"id": "logging-api",
"rule": "Reject printf() or stdio logging. Enforce FRR's zlog_* API (zlog_debug, zlog_err, zlog_warn, zlog_info, zlog_notice) and structured error macros flog_err(), flog_warn(), flog_err_sys() (which require an EC_* error-code argument). All debug statements MUST be guarded with CLI-controllable debug flags — unguarded debug prints are unacceptable at scale.",
"scope": ["**/*.c", "**/*.h", "**/*.cpp"],
"severity": "high"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Ambiguous "stdio logging" phrase leaves common bypass patterns uncovered

"Reject printf() or stdio logging" is loose enough that a model could accept fprintf(stderr, ...), fputs(msg, stderr), or fwrite to stderr — all of which bypass the zlog_* system entirely. FRR's logging.rst notes that startup stderr output is only valid before zlog_startup_end() is called; after that, direct writes to stderr are wrong. Enumerating the forbidden functions explicitly (e.g. fprintf, fputs, fwrite, perror) removes ambiguity and produces deterministic enforcement.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .greptile/config.json
Line: 32-35

Comment:
**Ambiguous "stdio logging" phrase leaves common bypass patterns uncovered**

"Reject printf() or stdio logging" is loose enough that a model could accept `fprintf(stderr, ...)`, `fputs(msg, stderr)`, or `fwrite` to stderr — all of which bypass the `zlog_*` system entirely. FRR's `logging.rst` notes that startup stderr output is only valid before `zlog_startup_end()` is called; after that, direct writes to stderr are wrong. Enumerating the forbidden functions explicitly (e.g. `fprintf`, `fputs`, `fwrite`, `perror`) removes ambiguity and produces deterministic enforcement.

How can I resolve this? If you propose a fix, please make it concise.

@suphawitwanl suphawitwanl merged commit 52c17b2 into master Apr 28, 2026
19 checks passed
@suphawitwanl
Copy link
Copy Markdown

@greptileai anything i could improve more

Comment thread .greptile/config.json
Comment on lines +26 to +29
"id": "memory-allocation",
"rule": "NEVER allow standard malloc(), calloc(), realloc(), or free(). Enforce FRR's XCALLOC, XMALLOC, XREALLOC, XSTRDUP, and XFREE macros (requires MTYPE). Every allocation must use the MTYPE tracking system declared via DECLARE_MTYPE/DEFINE_MTYPE. Prefer DEFINE_MTYPE_STATIC for module-private types.",
"scope": ["**/*.c", "**/*.h", "**/*.cpp"],
"severity": "critical"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 strdup/strndup not banned, leaving a MTYPE-bypass vector open

The memory-allocation rule explicitly bans malloc, calloc, realloc, and free but silently omits strdup() and strndup(). Both perform a raw heap allocation with no MTYPE tracking — they are functionally equivalent to malloc + strcpy from the memory-accounting perspective. The codebase already contains multiple .c files using bare strdup() (confirmed via search), which is exactly the pattern this ruleset is supposed to catch and flag. The correct FRR replacement (XSTRDUP(MTYPE_*, ...)) is already named in the rule text, so the missing piece is simply declaring the banned side:

"NEVER allow standard malloc(), calloc(), realloc(), strdup(), strndup(), or free(). ..."

Without this addition, strdup() calls will pass automated review silently.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .greptile/config.json
Line: 26-29

Comment:
**`strdup`/`strndup` not banned, leaving a MTYPE-bypass vector open**

The memory-allocation rule explicitly bans `malloc`, `calloc`, `realloc`, and `free` but silently omits `strdup()` and `strndup()`. Both perform a raw heap allocation with no MTYPE tracking — they are functionally equivalent to `malloc` + `strcpy` from the memory-accounting perspective. The codebase already contains multiple `.c` files using bare `strdup()` (confirmed via search), which is exactly the pattern this ruleset is supposed to catch and flag. The correct FRR replacement (`XSTRDUP(MTYPE_*, ...)`) is already named in the rule text, so the missing piece is simply declaring the banned side:

```
"NEVER allow standard malloc(), calloc(), realloc(), strdup(), strndup(), or free(). ..."
```

Without this addition, `strdup()` calls will pass automated review silently.

How can I resolve this? If you propose a fix, please make it concise.

@suphawitwanl
Copy link
Copy Markdown

@greptileai what about flow or sequence diagram that you not provided in some pr? how can i fix it

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 30, 2026

You can trigger a diagram from me at any time by asking directly in a PR comment — just say something like "generate a diagram", "generate a flowchart", or "show me a sequence diagram". I'll generate one based on the PR context.

Here's a flowchart for this PR showing how the three rules are enforced:

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[C/C++ Source File\n*.c / *.h / *.cpp] --> B{Greptile Rule Engine\nStrictness: 2}

    B --> C[memory-allocation rule\nSeverity: critical P0]
    B --> D[string-safety rule\nSeverity: high P1]
    B --> E[logging-api rule\nSeverity: medium P2]

    C --> C1{Uses raw malloc/\ncalloc/realloc/free?}
    C1 -- Yes --> C2[FAIL: Must use\nXMALLOC/XCALLOC/\nXREALLOC/XFREE]
    C1 -- No --> C3{MTYPE declared via\nDECLARE_MTYPE/\nDEFINE_MTYPE?}
    C3 -- No --> C4[FAIL: Missing\nMTYPE tracking]
    C3 -- Yes --> C5[PASS]

    D --> D1{Uses strcpy/strcat\n/sprintf?}
    D1 -- Yes --> D2[FAIL: Must use\nstrlcpy/strlcat/\nsnprintf]
    D1 -- No --> D3{Buffer size arg\nuses sizeof?}
    D3 -- No --> D4[FAIL: Must use\nsizeof for buffer size]
    D3 -- Yes --> D5[PASS]

    E --> E1{Uses printf\nor stdio?}
    E1 -- Yes --> E2[FAIL: Must use\nzlog_*/flog_* API]
    E1 -- No --> E3{Debug statements\nguarded by CLI\ndebug flags?}
    E3 -- No --> E4[FAIL: Missing\ndebug flag guard]
    E3 -- Yes --> E5[PASS]

    C5 --> F{All Rules Pass?}
    D5 --> F
    E5 --> F
    C2 --> G[Status Check FAILS\nBlock Merge]
    C4 --> G
    D2 --> G
    D4 --> G
    E2 --> G
    E4 --> G
    F -- Yes --> H[Status Check PASSES\nAllow Merge]
Loading

The flow shows each rule's check sequence — a single failure from any of the three blocks the merge via the status check.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants