Skip to content

Fix curvePoint.Equal() mutating its operands#626

Merged
pierluca merged 2 commits intodedis:masterfrom
eljobe:fix/curvepoint-equal-mutation
Apr 14, 2026
Merged

Fix curvePoint.Equal() mutating its operands#626
pierluca merged 2 commits intodedis:masterfrom
eljobe:fix/curvepoint-equal-mutation

Conversation

@eljobe
Copy link
Copy Markdown
Contributor

@eljobe eljobe commented Mar 21, 2026

Summary

  • Equal() was calling big.Int.Mod in place on both the receiver's and argument's x/y coordinates, mutating them as a side effect of what should be a read-only comparison. Fixed by using temporary big.Int values.
  • Set() and Clone() copied big.Int pointers rather than values, so any mutation (e.g. via Equal) on one point would silently corrupt aliased points. Fixed by deep-copying with new(big.Int).Set(...).
  • Base() assigned the curve's global Gx/Gy pointers directly, meaning mutations could corrupt the canonical generator. Fixed by deep-copying.

Fixes #625

Test plan

  • Added TestEqualDoesNotMutate — verifies Equal doesn't normalize the receiver
  • Added TestEqualDoesNotMutateArgument — verifies Equal doesn't normalize the argument
  • Added TestSetDeepCopies — verifies Set doesn't alias big.Int pointers
  • Added TestCloneDeepCopies — verifies Clone doesn't alias big.Int pointers
  • Added TestBaseDeepCopies — verifies Base doesn't alias curve generator pointers
  • All existing group/p256 tests pass (TestQR512, TestP256, TestSetBytesBE, TestVectors)

🤖 Generated with Claude Code

Equal() was calling big.Int.Mod in place on both operands' coordinates,
which violated the read-only contract of an equality test. Additionally,
Set(), Clone(), and Base() copied big.Int pointers rather than values,
meaning mutation in Equal could corrupt aliased points — including the
curve's global generator coordinates.

Fix by using temporary big.Ints in Equal and deep-copying in Set, Clone,
and Base.

Fixes dedis#625

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

🔒 Could not start CI tests due to missing safe PR label. Please contact a DEDIS maintainer.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 21, 2026

CLA assistant check
All committers have signed the CLA.

@jbsv jbsv added the safe PR label Mar 30, 2026
@jbsv jbsv requested review from AnomalRoil and thehoul March 30, 2026 12:16
@eljobe
Copy link
Copy Markdown
Contributor Author

eljobe commented Apr 2, 2026

@thehoul and @AnomalRoil, are you able to provide any estimate on how long you will require for PR review? I'm just trying to estimate how long we'll need to keep the work-around in our codebase.

1 similar comment
@eljobe
Copy link
Copy Markdown
Contributor Author

eljobe commented Apr 9, 2026

@thehoul and @AnomalRoil, are you able to provide any estimate on how long you will require for PR review? I'm just trying to estimate how long we'll need to keep the work-around in our codebase.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Apr 9, 2026

@AnomalRoil
Copy link
Copy Markdown
Contributor

@eljobe I can give it a review on Monday.

If you want to speed things up on my side you could run your test against the v3 codebase just to confirm whether this is a regression in v4 or has been there for a while.

@eljobe
Copy link
Copy Markdown
Contributor Author

eljobe commented Apr 10, 2026

@eljobe I can give it a review on Monday.

If you want to speed things up on my side you could run your test against the v3 codebase just to confirm whether this is a regression in v4 or has been there for a while.

Yes. It also fails in v3.1.1.

Reproduction steps:

git co v3.1.1
git switch -c failing-p256-equals
git checkout fix/curvepoint-equal-mutation -- group/p256/equal_mutation_test.go
go test ./group/p256/ -run "EqualDoesNotMutate|DeepCopies"
--- FAIL: TestEqualDoesNotMutate (0.00s)
    equal_mutation_test.go:29:
                Error Trace:    /Users/pepper/dev/github.com/eljobe/kyber/group/p256/equal_mutation_test.go:29
                Error:          Should not be: 0
                Test:           TestEqualDoesNotMutate
                Messages:       Equal() should not normalize the receiver's coordinates
--- FAIL: TestEqualDoesNotMutateArgument (0.00s)
    equal_mutation_test.go:45:
                Error Trace:    /Users/pepper/dev/github.com/eljobe/kyber/group/p256/equal_mutation_test.go:45
                Error:          Should not be: 0
                Test:           TestEqualDoesNotMutateArgument
                Messages:       Equal() should not normalize the argument's coordinates
--- FAIL: TestSetDeepCopies (0.00s)
    equal_mutation_test.go:58:
                Error Trace:    /Users/pepper/dev/github.com/eljobe/kyber/group/p256/equal_mutation_test.go:58
                Error:          Expected and actual point to the same object: 0x683f25c8f20 55492553260493539607289842316101867500450474346541697459824466285932216775873
                Test:           TestSetDeepCopies
                Messages:       Set should deep-copy x, not alias the pointer
--- FAIL: TestCloneDeepCopies (0.00s)
    equal_mutation_test.go:70:
                Error Trace:    /Users/pepper/dev/github.com/eljobe/kyber/group/p256/equal_mutation_test.go:70
                Error:          Expected and actual point to the same object: 0x683f25c9080 105557141625157029006948820755901011340931366098726400197237735504743005796895
                Test:           TestCloneDeepCopies
                Messages:       Clone should deep-copy x, not alias the pointer
--- FAIL: TestBaseDeepCopies (0.00s)
    equal_mutation_test.go:82:
                Error Trace:    /Users/pepper/dev/github.com/eljobe/kyber/group/p256/equal_mutation_test.go:82
                Error:          Expected and actual point to the same object: 0x683f25c8200 48439561293906451759052585252797914202762949526041747995844080717082404635286
                Test:           TestBaseDeepCopies
                Messages:       Base should deep-copy Gx, not alias the curve parameter
FAIL
FAIL    go.dedis.ch/kyber/v4/group/p256 0.312s
FAIL

Would it be helpful for me to push that branch to my fork?

Copy link
Copy Markdown
Contributor

@AnomalRoil AnomalRoil left a comment

Choose a reason for hiding this comment

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

LGTM

@pierluca pierluca merged commit 3194be0 into dedis:master Apr 14, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

curvePoint.Equal() mutates both receiver and argument

5 participants