Skip to content

Conversation

Marcofann
Copy link
Contributor

@Marcofann Marcofann commented Aug 25, 2025

  • Bounds-check seconds against MaxDurationSeconds to prevent int64 overflow/underflow
  • Enforce nanos ∈ [-999999999, 999999999]
  • Require consistent signs between seconds and nanos
  • Keep output as quoted total nanoseconds (no change in format)
  • Add unit tests: valid case, invalid nanos range, sign mismatch, overflow/underflow

Files:

  • x/tx/signing/aminojson/time.go
  • x/tx/signing/aminojson/time_test.go

Summary by CodeRabbit

  • New Features
    • More robust duration handling now outputs total nanoseconds as a JSON string.
  • Bug Fixes
    • Added validations to prevent overflow/underflow for very large or negative durations.
    • Enforced valid nanosecond ranges and consistent signs between seconds and nanoseconds, with clear error messages for invalid inputs.
  • Tests
    • Added comprehensive tests covering valid durations, invalid nanosecond ranges, sign mismatches, and overflow/underflow scenarios to ensure reliable behavior.

@Marcofann Marcofann changed the title aminojson: validate Duration in marshalDuration; add unit tests fix: validate Duration in marshalDuration; add unit tests Aug 25, 2025
Copy link
Contributor

coderabbitai bot commented Aug 25, 2025

📝 Walkthrough

Walkthrough

Adds stricter validation logic in aminojson marshalDuration for protobuf Duration semantics and introduces unit tests covering valid, range, sign, and overflow/underflow scenarios.

Changes

Cohort / File(s) Summary
Duration marshaling validation
x/tx/signing/aminojson/time.go
Implements runtime checks: seconds overflow/underflow against MaxDurationSeconds, nanos in [-999999999, 999999999], and sign consistency between seconds and nanos. Preserves field presence checks and outputs total nanoseconds as a JSON string.
Unit tests for duration marshaling
x/tx/signing/aminojson/time_test.go
Adds tests for valid duration, invalid nanos range, sign mismatch, and overflow/underflow using durationpb and MaxDurationSeconds. Verifies JSON string output and error conditions.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as Caller
  participant M as marshalDuration
  participant P as protobuf.Duration
  participant W as Writer/Encoder

  C->>M: marshalDuration(ctx, P.ProtoReflect(), W)
  M->>P: Read seconds, nanos
  alt missing fields
    M-->>C: error (missing seconds/nanos)
  else validate ranges
    alt seconds overflow/underflow
      M-->>C: error (seconds out of range)
    else nanos not in [-999999999, 999999999]
      M-->>C: error (nanos out of range)
    else sign mismatch (sec vs nanos)
      M-->>C: error (sign mismatch)
    else
      M->>M: totalNanos = sec*1e9 + nanos
      M->>W: write totalNanos as JSON string
      M-->>C: nil
    end
  end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
x/tx/signing/aminojson/time.go (1)

75-83: Nanos range and sign checks are correct; consider minor robustness/readability tweaks

The validations enforce protobuf Duration semantics well. Two small improvements:

  • Use typed int64 constants to avoid any ambiguity with untyped 1e9 and make intent clearer.
  • Include the offending values in the sign-mismatch error and clarify the “either may be zero” exception.

Apply this diff within the changed lines:

- // validate nanos range according to protobuf Duration constraints
- if nanos <= -1e9 || nanos >= 1e9 {
-   return fmt.Errorf("nanos must be in range [-999999999, 999999999], got %d", nanos)
- }
+ // validate nanos range according to protobuf Duration constraints
+ if nanos <= -int64(1_000_000_000) || nanos >= int64(1_000_000_000) {
+   return fmt.Errorf("nanos must be in range [-999999999, 999999999], got %d", nanos)
+ }

- // seconds and nanos must have consistent signs
- if (seconds > 0 && nanos < 0) || (seconds < 0 && nanos > 0) {
-   return fmt.Errorf("seconds and nanos must have the same sign")
- }
+ // seconds and nanos must have consistent signs (or either may be zero)
+ if (seconds > 0 && nanos < 0) || (seconds < 0 && nanos > 0) {
+   return fmt.Errorf("seconds and nanos must have the same sign (or either may be zero): seconds=%d nanos=%d", seconds, nanos)
+ }

Optional (outside the changed ranges): define named constants once for readability.

// near top of file
const (
    nanosPerSecond int64 = 1_000_000_000
    minNanos       int64 = -999_999_999
    maxNanos       int64 =  999_999_999
)

Then use nanosPerSecond in the total computation (line 84) for clarity:

totalNanos := nanos + (seconds * nanosPerSecond)

Also applies to: 84-86

x/tx/signing/aminojson/time_test.go (3)

10-26: Happy path test LGTM; tiny style nit

The assertion matches the output format and math. Style-wise, constructing the message directly is a bit clearer than creating with durationpb.New(0) and then mutating fields.

- msg := durationpb.New(0)
- // 1 second and 500 nanos => 1_000_000_000 + 500
- msg.Seconds = 1
- msg.Nanos = 500
+ // 1 second and 500 nanos => 1_000_000_000 + 500
+ msg := &durationpb.Duration{Seconds: 1, Nanos: 500}

28-37: Range checks covered; consider asserting boundary acceptance at ±999,999,999

You cover the rejection of ±1,000,000,000. Adding a positive assertion that ±999,999,999 are accepted would harden boundary coverage.

I can push a follow-up test if you’d like.


57-69: Overflow/underflow checks are correct; add max-boundary “still OK” assertions

The tests verify we reject seconds just outside the bound. Consider adding “on the edge” positive tests to ensure seconds == MaxDurationSeconds with aligned nanos still marshal successfully.

Here are additive tests you can append (also exercises zero-seconds with signed nanos):

@@
 func TestMarshalDuration_OverflowUnderflow(t *testing.T) {
@@
 }
+
+func TestMarshalDuration_BoundaryValuesAllowed(t *testing.T) {
+    t.Parallel()
+    cases := []struct{
+        name    string
+        seconds int64
+        nanos   int32
+    }{
+        {"max_seconds_zero_nanos", MaxDurationSeconds, 0},
+        {"max_seconds_max_nanos", MaxDurationSeconds, 999_999_999},
+        {"min_seconds_zero_nanos", -MaxDurationSeconds, 0},
+        {"min_seconds_min_nanos", -MaxDurationSeconds, -999_999_999},
+        {"zero_seconds_pos_nanos", 0, 999_999_999},
+        {"zero_seconds_neg_nanos", 0, -999_999_999},
+    }
+    for _, tc := range cases {
+        t.Run(tc.name, func(t *testing.T) {
+            msg := &durationpb.Duration{Seconds: tc.seconds, Nanos: tc.nanos}
+            var buf bytes.Buffer
+            if err := marshalDuration(nil, msg.ProtoReflect(), &buf); err != nil {
+                t.Fatalf("unexpected error for %s: %v", tc.name, err)
+            }
+        })
+    }
+}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Knowledge Base: Disabled due to Reviews > Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 79fcc30 and 8db508c.

📒 Files selected for processing (2)
  • x/tx/signing/aminojson/time.go (1 hunks)
  • x/tx/signing/aminojson/time_test.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Summary
🔇 Additional comments (2)
x/tx/signing/aminojson/time.go (1)

61-67: Good guard against int64 overflow/underflow from seconds→nanoseconds conversion

The explicit bounds on seconds vs MaxDurationSeconds look correct and prevent overflow in the subsequent seconds*1e9 multiplication.

x/tx/signing/aminojson/time_test.go (1)

39-55: Sign-mismatch tests are precise and effective

The table captures both mismatch directions succinctly. No issues.

@aljo242
Copy link
Contributor

aljo242 commented Aug 29, 2025

@Marcofann lint is failing

@aljo242
Copy link
Contributor

aljo242 commented Aug 29, 2025

needs a changelog as well

@Marcofann
Copy link
Contributor Author

@aljo242 Thanks for the feedback! I've fixed both issues:

  1. Lint errors resolved: Fixed the gci import formatting in time_test.go by applying proper import ordering and gofumpt formatting according to the project's .golangci.yml config.

  2. Changelog added: Added an entry in CHANGELOG.md for this PR in the "Bug Fixes" section.

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.

2 participants