modular / modular/modular

[BUG] `Int` division by zero is silently undefined: returns garbage, returns 0, or crashes with an unsymbolicated stack trace

Open
#6,898 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug mojo Mojo Libraries needs-discussion
Dominant language
Mojo
Stars
29.8k
Forks
3.2k
PR merge metrics
No merged PRs in 30d

Description

Bug description
Actual behavior

Dividing an Int by zero has no defined behaviour. Depending on how the
denominator reaches the division, the same operation either returns a
nondeterministic value, returns 0, or crashes the process with a raw stack
dump. Nothing in the operators documentation
mentions division by zero, so there is no way to know this without testing for it.

Expected behavior

Python — whose syntax and semantics Mojo otherwise follows closely — raises
ZeroDivisionError here. Code ported from Python silently produces wrong
results instead of failing.

So either:

  1. Python parity — raise ZeroDivisionError, or
  2. if the branch is considered too expensive for hot paths: document it as
    undefined behaviour
    in the operators manual, and trap it in debug builds
    (as Rust does), so it fails loudly during development rather than corrupting
    data silently.

The current state is the worst of both: undocumented, inconsistent between
operators, and inconsistent between runs of the same program.

Steps to reproduce
A. Hard crash
def divide(numerator: Int, denominator: Int) -> Int:
    return numerator / denominator

def main():
    var values = [7, 0, 3]
    for v in values:
        print(v, "->", divide(100, v))

Output (identical across 3 runs):

7 -> 14 #0 0x000076c2505bef8e (.../libKGENCompilerRTShared.so+0xfbf8e)
#1 0x000076c2505bc0a6 (.../libKGENCompilerRTShared.so+0xf90a6)
#2 0x000076c2505bfdd0 (.../libKGENCompilerRTShared.so+0xfcdd0)
#3 0x000076c253645330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
#4 0x000076c21c0011a7
mojo: error: execution crashed

The message never mentions division by zero.

B. Silent nondeterministic value
def divide(numerator: Int, denominator: Int) -> Int:
    return numerator / denominator

def main():
    var segments = 7
    var duration = 5
    var steps = duration / segments   # == 0
    print("computed denominator:", divide(3, steps))

    var zero = 0
    print("constant denominator:", divide(3, zero))

Three consecutive runs:

computed denominator: 0   constant denominator: 140736790674968
computed denominator: 0   constant denominator: 140726301657880
computed denominator: 0   constant denominator: 140736819750648

The second value changes on every run and looks like a stack address. Which of
the two operands produces garbage versus 0 is not stable either — in a
slightly different arrangement of the same code the roles were reversed.

C. // and %

With the same list-based shape that crashes for /, both // and % instead
return 0 silently:

def main():
    var values = [0]
    for v in values:
        print("floordiv:", 100 // v)   # 0
        print("mod:", 100 % v)         # 0
System information

System

   Pixi version: 0.76.0
    TLS backend: rustls
       Platform: linux-64

Virtual packages: __unix=0=0
: __linux=6.8.0=0
: __glibc=2.39=0
: __archspec=1=skylake
Cache dir: /home/stefan/.cache/rattler/cache
Auth storage: /home/stefan/.rattler/credentials.json
Config locations: No config files found

Global

        Bin dir: /home/stefan/.pixi/bin
Environment dir: /home/stefan/.pixi/envs
   Manifest dir: /home/stefan/.pixi/manifests/pixi-global.toml

As I am using uv:
uv pip list
Package Version


click 8.4.2
mblack 26.5.0
mojo 1.0.0
mojo-compiler 1.0.0
mojo-compiler-mojo-libs 1.0.0
mojo-lldb-libs 1.0.0
mypy-extensions 1.1.0
pathspec 1.1.1
platformdirs 4.11.2

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the three reproductions for /, //, and % to confirm the inconsistent zero-denominator behavior, then read the operators documentation linked in the issue. The work is complete when the project has an agreed zero-division behavior, applies it consistently across these operators, and documents the resulting behavior or failure mode.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.