Skip to content

Fix 32-bit architecture compilation failures in varint, cqlint, and decimal serialization#714

Draft
Copilot wants to merge 6 commits intomasterfrom
copilot/fix-arm32-support-errors
Draft

Fix 32-bit architecture compilation failures in varint, cqlint, and decimal serialization#714
Copilot wants to merge 6 commits intomasterfrom
copilot/fix-arm32-support-errors

Conversation

Copy link
Copy Markdown

Copilot AI commented Feb 15, 2026

Compilation failed on 32-bit architectures (ARM, x86) due to integer overflow in constants and shifts that exceed 32-bit int range. Constants like int(-1) << 32 and maxInt40 = 1<<39 - 1 overflowed when int is 32 bits.

Changes

Architecture-specific implementations

  • 64-bit (amd64, arm64, etc.): Full int support up to 8 bytes
  • 32-bit (386, arm, mips, etc.): int limited to 4 bytes; rejects oversized data

Packages Fixed

varint package:

  • marshal_ints_{32bit,64bit}.go - Marshal functions
  • unmarshal_ints_{32bit,64bit}.go - Unmarshal functions and helpers
  • marshal_utils_{32bit,64bit}.go - Constants (untyped on 64-bit, int64 on 32-bit)
  • marshal_ints.go, unmarshal_ints.go, marshal_utils.go - Removed architecture-dependent code

cqlint package:

  • unmarshal_utils_{32bit,64bit}.go - Architecture-specific decInt function
  • unmarshal_utils.go - Removed architecture-dependent code
  • unmarshal_utils_arch_test.go - Unit tests for architecture-specific behavior

decimal package:

  • unmarshal_ints.go - Removed unused neg32Int constant that would overflow on 32-bit

Behavior

64-bit: No change
32-bit: int operations limited to ±2³¹ range (correct for 32-bit systems)
int64: Unchanged on all architectures

Testing

  • ✅ All tests pass on both 32-bit and 64-bit architectures
  • ✅ Verified compilation on amd64, 386, arm, and mips architectures
  • ✅ Round-trip encoding/decoding tests confirm correctness
  • ✅ Architecture-specific unit tests added for varint and cqlint packages

Build constraints: (amd64 || arm64 || ppc64 || ppc64le || mips64 || mips64le || s390x || riscv64 || loong64) && !gocql_32bit for 64-bit, (386 || arm || mips || mipsle) || gocql_32bit for 32-bit.

Original prompt

This section details on the original issue you should resolve

<issue_title>switch to 1.17.1 broke arm 32 support</issue_title>
<issue_description>The build is now failing with compilation errors in scylladb/gocql v1.17.1. The errors show integer overflow issues on 32-bit architectures (Linux ARM):

../go/pkg/mod/github.com/scylladb/gocql@v1.17.1/serialization/varint/unmarshal_ints.go:25:14: int(-1) << 32 (constant -4294967296 of type int) overflows int
../go/pkg/mod/github.com/scylladb/gocql@v1.17.1/serialization/varint/unmarshal_ints.go:26:14: int(-1) << 40 (constant -1099511627776 of type int) overflows int
../go/pkg/mod/github.com/scylladb/gocql@v1.17.1/serialization/varint/unmarshal_ints.go:27:14: int(-1) << 48 (constant -281474976710656 of type int) overflows int
../go/pkg/mod/github.com/scylladb/gocql@v1.17.1/serialization/varint/unmarshal_ints.go:28:14: int(-1) << 56 (constant -72057594037927936 of type int) overflows int
../go/pkg/mod/github.com/scylladb/gocql@v1.17.1/serialization/varint/marshal_ints.go:120:10: maxInt40 (untyped int constant 549755813887) overflows int
../go/pkg/mod/github.com/scylladb/gocql@v1.17.1/serialization/varint/marshal_ints.go:120:27: minInt40 (untyped int constant -549755813888) overflows int
../go/pkg/mod/github.com/scylladb/gocql@v1.17.1/serialization/varint/marshal_ints.go:123:10: maxInt48 (untyped int constant 140737488355327) overflows int
../go/pkg/mod/github.com/scylladb/gocql@v1.17.1/serialization/varint/marshal_ints.go:123:27: minInt48 (untyped int constant -140737488355328) overflows int
../go/pkg/mod/github.com/scylladb/gocql@v1.17.1/serialization/varint/marshal_ints.go:126:10: maxInt56 (untyped int constant 36028797018963967) overflows int
../go/pkg/mod/github.com/scylladb/gocql@v1.17.1/serialization/varint/marshal_ints.go:126:27: minInt56 (untyped int constant -36028797018963968) overflows int

</issue_description>

<agent_instructions>Please see the issue and suggest why on 32bit architecture we may be getting this error. Suggest a fix with a unit test</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@mykaul Does it happen on 64bit ARM as well? If not, I suggest to block support on 32bit.

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 4 commits February 15, 2026 11:49
Co-authored-by: mykaul <4655593+mykaul@users.noreply.github.com>
Co-authored-by: mykaul <4655593+mykaul@users.noreply.github.com>
Co-authored-by: mykaul <4655593+mykaul@users.noreply.github.com>
Co-authored-by: mykaul <4655593+mykaul@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix compilation errors for arm 32 support in gocql Fix 32-bit architecture compilation failures in varint serialization Feb 15, 2026
Copilot AI requested a review from mykaul February 15, 2026 11:59
@mykaul
Copy link
Copy Markdown

mykaul commented Feb 15, 2026

@copilot - thanks - what other CQL types need similar marshaling/unmarshaling code for 32bit vs 64bit?

Copy link
Copy Markdown
Author

Copilot AI commented Feb 15, 2026

@copilot - thanks - what other CQL types need similar marshaling/unmarshaling code for 32bit vs 64bit?

After analyzing the serialization package, I found that two additional CQL types need similar fixes for 32-bit architectures:

  1. cqlint (CQL int type) - Has negInt = int(-1) << 32 constant that overflows on 32-bit
  2. decimal - Has neg32Int = int(-1) << 32 constant that overflows on 32-bit

The tinyint and smallint types are safe because they only shift by 8 and 16 bits respectively.

I can apply the same architecture-specific build constraint approach to fix cqlint and decimal. Would you like me to proceed with those fixes as well?

@mykaul
Copy link
Copy Markdown

mykaul commented Feb 15, 2026

@copilot - thanks - what other CQL types need similar marshaling/unmarshaling code for 32bit vs 64bit?

After analyzing the serialization package, I found that two additional CQL types need similar fixes for 32-bit architectures:

  1. cqlint (CQL int type) - Has negInt = int(-1) << 32 constant that overflows on 32-bit
  2. decimal - Has neg32Int = int(-1) << 32 constant that overflows on 32-bit

The tinyint and smallint types are safe because they only shift by 8 and 16 bits respectively.

I can apply the same architecture-specific build constraint approach to fix cqlint and decimal. Would you like me to proceed with those fixes as well?

@copilot , yes please. Follow-up with those as well.

Co-authored-by: mykaul <4655593+mykaul@users.noreply.github.com>
Copy link
Copy Markdown
Author

Copilot AI commented Feb 15, 2026

@copilot - thanks - what other CQL types need similar marshaling/unmarshaling code for 32bit vs 64bit?

After analyzing the serialization package, I found that two additional CQL types n...

Applied the same architecture-specific fix to both cqlint and decimal packages in commit a3074d4.

Changes:

  • cqlint: Split decInt function into architecture-specific files (64-bit uses negInt = int(-1) << 32, 32-bit uses int32 for sign extension)
  • decimal: Removed unused neg32Int constant

All tests pass on both 32-bit and 64-bit architectures (amd64, 386, arm).

@mykaul
Copy link
Copy Markdown

mykaul commented Feb 15, 2026

@copilot - explain how in build time the right files are selected for compilation.

Copilot AI changed the title Fix 32-bit architecture compilation failures in varint serialization Fix 32-bit architecture compilation failures in varint, cqlint, and decimal serialization Feb 15, 2026
Copy link
Copy Markdown
Author

Copilot AI commented Feb 15, 2026

@copilot - explain how in build time the right files are selected for compilation.

Go's build system uses build constraints (also called build tags) at the top of source files to select which files to compile based on the target architecture.

How it works:

  1. Build constraint syntax: The first line //go:build (conditions) tells the Go compiler when to include this file

    • Example: //go:build (amd64 || arm64 || ppc64 || ...) && !gocql_32bit
  2. Automatic selection: When you run go build, the compiler:

    • Checks the GOOS and GOARCH environment variables (or defaults for your system)
    • Evaluates each file's build constraint against the current architecture
    • Only compiles files where the constraint evaluates to true
  3. Our implementation:

    • 64-bit files (*_64bit.go): Included when GOARCH is amd64, arm64, ppc64, etc.
    • 32-bit files (*_32bit.go): Included when GOARCH is 386, arm, mips, etc.
    • Common files (no constraint): Always included

Example: When building for ARM 32-bit (GOARCH=arm):

  • unmarshal_utils.go - compiled (no constraint)
  • unmarshal_utils_64bit.go - skipped (constraint evaluates to false)
  • unmarshal_utils_32bit.go - compiled (constraint evaluates to true)

This ensures the correct decInt function is used without any runtime overhead.

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.

switch to 1.17.1 broke arm 32 support

2 participants