Skip to content

Fix pointer_offset expressions in dump-c generated code#8880

Open
tautschnig wants to merge 1 commit intodiffblue:developfrom
tautschnig:dump-c-pointer_offset
Open

Fix pointer_offset expressions in dump-c generated code#8880
tautschnig wants to merge 1 commit intodiffblue:developfrom
tautschnig:dump-c-pointer_offset

Conversation

@tautschnig
Copy link
Collaborator

When goto-instrument --dump-c converts a goto program back to C, pointer comparisons like &arr[i][j] == &arr[x][y] get simplified by the expression simplifier into pointer_offset arithmetic. The pointer_offset_exprt is then rendered as __CPROVER_POINTER_OFFSET by expr2c, which is not valid C and cannot be compiled by GCC.

The fix adds handling for pointer_offset expressions in dump_ct's cleanup_expr. It converts pointer_offset(p) to the equivalent C expression ((char*)(p) - (char*)&root_object), where root_object is found by unwrapping address_of, index, member, and typecast operations from the pointer operand.

Minimal reproducer:
int l[10][10]; int g;
int main(void) { if(&l[g+2][g] == &l[3][3]) return 1; return 0; }

This was found via CSmith test seed 1750841832.

  • Each commit message has a non-empty body, explaining why the change was made.
  • n/a Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • n/a The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • n/a My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • n/a White-space or formatting changes outside the feature-related changed lines are in commits of their own.

When goto-instrument --dump-c converts a goto program back to C, pointer
comparisons like &arr[i][j] == &arr[x][y] get simplified by the
expression simplifier into pointer_offset arithmetic. The
pointer_offset_exprt is then rendered as __CPROVER_POINTER_OFFSET by
expr2c, which is not valid C and cannot be compiled by GCC.

The fix adds handling for pointer_offset expressions in dump_ct's
cleanup_expr. It converts pointer_offset(p) to the equivalent C
expression ((char*)(p) - (char*)&root_object), where root_object is
found by unwrapping address_of, index, member, and typecast operations
from the pointer operand.

Minimal reproducer:
  int l[10][10]; int g;
  int main(void) { if(&l[g+2][g] == &l[3][3]) return 1; return 0; }

This was found via CSmith test seed 1750841832.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@tautschnig tautschnig self-assigned this Mar 18, 2026
Copilot AI review requested due to automatic review settings March 18, 2026 11:35
Copy link

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

Fixes goto-instrument --dump-c emitting non-compilable __CPROVER_POINTER_OFFSET(...) by rewriting pointer_offset expressions into plain C pointer-difference arithmetic during expression cleanup.

Changes:

  • Add ID_pointer_offset handling in dump_ct::cleanup_expr to rewrite pointer_offset(p) into a C expression based on char * pointer subtraction.
  • Add a regression test ensuring --dump-c output does not contain __CPROVER_POINTER_OFFSET.
  • Add necessary include for pointer_offset_exprt helpers.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/goto-instrument/dump_c.cpp Rewrites pointer_offset expressions to avoid emitting __CPROVER_POINTER_OFFSET in dump-c output.
regression/goto-instrument/dump-c-pointer-offset/test.desc Regression harness: asserts dump-c succeeds and forbids __CPROVER_POINTER_OFFSET in output.
regression/goto-instrument/dump-c-pointer-offset/main.c Minimal reproducer that triggers simplification to pointer_offset during dump-c.

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

Comment on lines +1606 to +1631

// Find the root object by unwrapping address_of, index, member,
// and typecast operations
const exprt *obj = &ptr;
if(obj->id() == ID_address_of)
obj = &to_address_of_expr(*obj).object();
const exprt *root = obj;
while(root->id() == ID_index || root->id() == ID_typecast ||
root->id() == ID_member)
{
if(root->id() == ID_index)
root = &to_index_expr(*root).array();
else if(root->id() == ID_member)
root = &to_member_expr(*root).compound();
else
root = &to_typecast_expr(*root).op();
}

const typet char_ptr = pointer_type(char_type());
const typet result_type = expr.type();

exprt cast_ptr = typecast_exprt(ptr, char_ptr);
exprt cast_base = typecast_exprt(address_of_exprt(*root), char_ptr);
exprt diff = minus_exprt(cast_ptr, cast_base);
expr = typecast_exprt(diff, result_type);
cleanup_expr(expr);
@codecov
Copy link

codecov bot commented Mar 18, 2026

Codecov Report

❌ Patch coverage is 84.21053% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.41%. Comparing base (85c204f) to head (5fb96f6).

Files with missing lines Patch % Lines
src/goto-instrument/dump_c.cpp 84.21% 3 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #8880      +/-   ##
===========================================
- Coverage    80.41%   80.41%   -0.01%     
===========================================
  Files         1703     1703              
  Lines       188398   188417      +19     
  Branches        73       73              
===========================================
+ Hits        151498   151512      +14     
- Misses       36900    36905       +5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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