Skip to content

Conversation

@feniup
Copy link
Contributor

@feniup feniup commented May 7, 2025

Lab Course: Static Analysis with Goblint

In this lab course we try to actively contribute to the Goblint codebase by integrating new abstract domain.

In the current iteration, the focus is on the development of the pentagon domain (Pntg), which combines interval analysis with symbolic relational constraints of the form $x < y$. This hybrid approach offers greater precision than traditional interval analysis while maintaining lower complexity compared to more expressive domains like the octagon domain.

@michael-schwarz michael-schwarz added student-job relational Relational analyses (Apron, affeq, lin2var) feature labels May 7, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements the pentagon domain for the Goblint static analyzer as part of a lab course. The pentagon domain combines interval analysis with symbolic relational constraints of the form x < y, offering greater precision than traditional interval analysis while maintaining lower complexity than more expressive domains like octagons.

Changes:

  • Implemented core pentagon domain modules (ZExt, Intv, Subs, Boxes, Pntg) for managing extended integers, intervals, strict upper bounds, and the pentagon structure
  • Added pentagonDomain and pentagonAnalysis modules with Apron integration
  • Created regression test suite with 8 test cases covering various pentagon domain scenarios
  • Added configuration files for pentagon analysis

Reviewed changes

Copilot reviewed 23 out of 24 changed files in this pull request and generated 20 comments.

Show a summary per file
File Description
wrong_verdicts.md Documentation of known incorrect analysis verdicts
tests/unit/mainTest.ml Whitespace cleanup
tests/regression/89-pentagon/*.c Regression test suite for pentagon domain functionality
src/goblint_lib.ml Module exports for pentagon domain components
src/dune Build configuration for pentagon modules with Apron selection
src/cdomains/pentagon/zExt.ml Extended integer type with infinity support
src/cdomains/pentagon/intv.ml Interval arithmetic operations
src/cdomains/pentagon/subs.ml Strict upper bounds management
src/cdomains/pentagon/boxes.ml Collections of intervals
src/cdomains/pentagon/pntg.ml Main pentagon structure
src/cdomains/pentagon/stringUtils.ml String formatting utilities
src/cdomains/apron/pentagonDomain.*.ml Pentagon domain implementation with Apron integration
src/analyses/apron/pentagonAnalysis.*.ml Analysis specification using pentagon domain
conf/pentagon*.json Configuration files for pentagon analysis

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

module VarSet = struct
module IdxSet = BatSet.Make(Idx)
include IdxSet
let hash t = IdxSet.fold (fun idx acc -> acc lxor (19 * idx + 0x9e3779b9)) t 0
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The hash function implementation using a custom fold with XOR and magic number (0x9e3779b9) is non-standard and potentially problematic. The magic number appears to be added/xored incorrectly for combining hash values. Consider using a more standard approach like "IdxSet.fold (fun idx acc -> acc * 31 + idx) t 0" or similar established hash combination methods.

Suggested change
let hash t = IdxSet.fold (fun idx acc -> acc lxor (19 * idx + 0x9e3779b9)) t 0
let hash t = IdxSet.fold (fun idx acc -> acc * 31 + idx) t 0

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +50
if dim_change.realdim != 0 then
failwith "Pentagons are defined over integers: \
extension with real domain is nonsensical"
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

Inconsistent comparison operator usage. The code uses "!=" for comparing with 0, but throughout the rest of the codebase, "<>" is the standard OCaml inequality operator. For consistency, use "dim_change.realdim <> 0".

Copilot uses AI. Check for mistakes.
| z1, PosInfty when sign z1 < 0 -> failwith "ZExt.pow: Cannot determine whether result is NegInfty or PosInfty (or -1 or 1 for z1 = -1) -> depends on the side of the interval"
| PosInfty, _ | _, PosInfty -> PosInfty
| NegInfty, Arb z -> if Z.is_even z then PosInfty else NegInfty
| _, NegInfty -> failwith "This shouldn't happen (caught in second line of ZExt.pow)"
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The comment contains inline code that uses backticks instead of proper inline code delimiters, and includes an unclear reference to "(caught in second line of ZExt.pow)". This error message should be more specific about what the actual issue is and provide actionable guidance.

Suggested change
| _, NegInfty -> failwith "This shouldn't happen (caught in second line of ZExt.pow)"
| _, NegInfty ->
failwith "ZExt.pow: exponent must be a finite, non-negative value; negative infinity as an exponent is not supported."

Copilot uses AI. Check for mistakes.
in
(** Counts the number of empty sets to prepend at the current index. *)
let append_count =
Array.count_matching (fun k -> k == i) dim_change.dim
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The comparison uses "==" instead of the structural equality operator "=". In OCaml, "==" tests physical equality (same memory location), while "=" tests structural equality (same value). For integer comparison, you should use "=" instead. This applies to both comparisons on this line.

Copilot uses AI. Check for mistakes.
if lb_correction_term = PosInfty then (const_lb, [y]) else (ZExt.add const_lb lb_correction_term, [y])
| l -> (
if lb_correction_term = PosInfty then
failwith "This should not happen."
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The error message "This should not happen." is vague and provides no context for debugging. Consider replacing with something more specific like "Internal error: Unexpected PosInfty in correction term when lower bound infinity list has length >= 2" to help with debugging.

Copilot uses AI. Check for mistakes.
Comment on lines +161 to +165
let lt ((_, ub1):t) ((lb2, _):t) =
ub1 < lb2

let gt ((lb1, _):t) ((_, ub2):t) =
lb1 > ub2
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The comparison operators (lt and gt) use OCaml's built-in comparison operators (<, >) directly on ZExt.t values without using the custom comparison operators defined in ZExtOps. This is inconsistent with the rest of the codebase which uses (<), (>), etc. Consider using "ub1 <* lb2" and "lb1 >* ub2" for consistency.

Suggested change
let lt ((_, ub1):t) ((lb2, _):t) =
ub1 < lb2
let gt ((lb1, _):t) ((_, ub2):t) =
lb1 > ub2
let lt ((_, ub1):t) ((lb2, _):t) =
ub1 <* lb2
let gt ((lb1, _):t) ((_, ub2):t) =
lb1 >* ub2

Copilot uses AI. Check for mistakes.
Comment on lines +54 to +56
if dim_change.realdim != 0 then
failwith "Pentagons are defined over integers: \
extension with real domain is nonsensical"
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

Inconsistent comparison operator usage. The code uses "!=" for comparing with 0, but throughout the rest of the codebase, "<>" is the standard OCaml inequality operator. For consistency, use "dim_change.realdim <> 0".

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +47
Array.count_matching (fun k -> k == i) dim_change.dim
in
(** Prepends n many empty sets to the accumulator. *)
let rec prepend_dim n acc =
if n == 0 then
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The comparison uses "==" instead of the structural equality operator "=". In OCaml, "==" tests physical equality (same memory location), while "=" tests structural equality (same value). For integer comparison, you should use "=" instead.

Suggested change
Array.count_matching (fun k -> k == i) dim_change.dim
in
(** Prepends n many empty sets to the accumulator. *)
let rec prepend_dim n acc =
if n == 0 then
Array.count_matching (fun k -> k = i) dim_change.dim
in
(** Prepends n many empty sets to the accumulator. *)
let rec prepend_dim n acc =
if n = 0 then

Copilot uses AI. Check for mistakes.
if ub_correction_term = NegInfty then (const_ub, [y]) else (ZExt.add const_ub ub_correction_term, [y])
| l -> (
if ub_correction_term = NegInfty then
failwith "This should not happen."
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The error message "This should not happen." is vague and provides no context for debugging. Consider replacing with something more specific like "Internal error: Unexpected NegInfty in correction term when upper bound infinity list has length >= 2" to help with debugging.

Suggested change
failwith "This should not happen."
failwith "Internal error: Unexpected NegInfty in correction term when upper bound infinity list has length >= 2"

Copilot uses AI. Check for mistakes.
Comment on lines +418 to +420

let to_yojson t = failwith "TODO"

Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

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

The to_yojson function is not implemented and just contains "failwith TODO". This is a placeholder that should either be implemented or removed before merging. If JSON serialization is not required for this domain, consider removing this function or documenting why it's intentionally unimplemented.

Suggested change
let to_yojson t = failwith "TODO"
(* JSON serialization uses the textual representation of the domain element. *)
let to_yojson (t:t) = `String (show t)

Copilot uses AI. Check for mistakes.
michael-schwarz and others added 2 commits January 20, 2026 23:43
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@sim642
Copy link
Member

sim642 commented Jan 21, 2026

What is the plan with this? Is it in working order and is the goal to still have it merged?

@DrMichaelPetter
Copy link
Collaborator

There are a few wrong verdicts still in there. This is on my list of things to fix, but for now we should not merge this.

@DrMichaelPetter DrMichaelPetter marked this pull request as draft January 22, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature in progress relational Relational analyses (Apron, affeq, lin2var) student-job

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants