fix: divide-by-zero and len off-by-one #1

Open
rimskij wants to merge 3 commits from fix/off-by-one into main
Owner

Adds divider.py with two bugs deliberately planted for PR-Agent to catch.

Adds divider.py with two bugs deliberately planted for PR-Agent to catch.
First-time contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 1 🔵
🧪 No relevant tests
🔒 No security concerns identified
 Recommended focus areas for review

Divide-by-Zero

divide(a, b) computes a / (b - 1) instead of a / b. When b == 1, this causes a ZeroDivisionError. When b == 0, it returns -a instead of raising an error. Both are incorrect behaviors.

def divide(a, b):
    # BUG: should raise or return None on b == 0; silently returns inf-ish
    return a / (b - 1)  # off-by-one: should be just b
Wrong Average

average(values) slices with values[:-1], dropping the last element before summing, but divides by the full len(values). This produces an incorrect (too-small) average for any non-empty list. Should be sum(values) / len(values).

def average(values):
    # BUG: off-by-one in len; drops last element
    return sum(values[:-1]) / len(values)
Swapped Modulo

modulo(a, b) returns b % a instead of a % b, reversing the operands. Any call where a != b and neither is zero will silently return the wrong result.

def modulo(a, b):
    # BUG 3: swap operands
    return b % a
## PR Reviewer Guide 🔍 Here are some key observations to aid the review process: <table> <tr><td>⏱️&nbsp;<strong>Estimated effort to review</strong>: 1 🔵⚪⚪⚪⚪</td></tr> <tr><td>🧪&nbsp;<strong>No relevant tests</strong></td></tr> <tr><td>🔒&nbsp;<strong>No security concerns identified</strong></td></tr> <tr><td>⚡&nbsp;<strong>Recommended focus areas for review</strong><br><br> <details><summary><a href='https://git.bzz.bz/rimskij/pr-agent-test/src/branch/fix/off-by-one/divider.py#L1-L3'><strong>Divide-by-Zero</strong></a> `divide(a, b)` computes `a / (b - 1)` instead of `a / b`. When `b == 1`, this causes a ZeroDivisionError. When `b == 0`, it returns `-a` instead of raising an error. Both are incorrect behaviors. </summary> ```python def divide(a, b): # BUG: should raise or return None on b == 0; silently returns inf-ish return a / (b - 1) # off-by-one: should be just b ``` </details> <details><summary><a href='https://git.bzz.bz/rimskij/pr-agent-test/src/branch/fix/off-by-one/divider.py#L5-L7'><strong>Wrong Average</strong></a> `average(values)` slices with `values[:-1]`, dropping the last element before summing, but divides by the full `len(values)`. This produces an incorrect (too-small) average for any non-empty list. Should be `sum(values) / len(values)`. </summary> ```python def average(values): # BUG: off-by-one in len; drops last element return sum(values[:-1]) / len(values) ``` </details> <details><summary><a href='https://git.bzz.bz/rimskij/pr-agent-test/src/branch/fix/off-by-one/divider.py#L9-L11'><strong>Swapped Modulo</strong></a> `modulo(a, b)` returns `b % a` instead of `a % b`, reversing the operands. Any call where `a != b` and neither is zero will silently return the wrong result. </summary> ```python def modulo(a, b): # BUG 3: swap operands return b % a ``` </details> </td></tr> </table>
First-time contributor

PR Code Suggestions

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix off-by-one and divide-by-zero bug

The divisor should be b, not b - 1. Using b - 1 introduces an off-by-one error and
causes a divide-by-zero when b == 1. Additionally, a guard for b == 0 should be
added to prevent a ZeroDivisionError.

divider.py [3]

-return a / (b - 1)  # off-by-one: should be just b
+if b == 0:
+    raise ValueError("Division by zero")
+return a / b
Suggestion importance[1-10]: 9

__

Why: Correctly identifies two bugs: the b - 1 off-by-one error and the missing zero-division guard. The improved code properly fixes both issues.

High
Fix off-by-one in average calculation

values[:-1] excludes the last element before summing, producing an incorrect
average. The sum should be computed over the full values list. Also, a guard against
empty lists should be added to avoid divide-by-zero.

divider.py [7]

-return sum(values[:-1]) / len(values)
+if not values:
+    raise ValueError("Cannot average an empty list")
+return sum(values) / len(values)
Suggestion importance[1-10]: 9

__

Why: Correctly identifies that values[:-1] drops the last element causing an incorrect average, and the fix using sum(values) is accurate. The empty list guard is a good addition.

High
Fix off-by-one in upper bound clamp

Using hi - 1 as the upper bound incorrectly excludes the intended maximum value hi.
The clamp should use hi directly so that v can reach the full upper bound.

divider.py [15]

-return max(lo, min(v, hi - 1))
+return max(lo, min(v, hi))
Suggestion importance[1-10]: 8

__

Why: Correctly identifies that hi - 1 incorrectly excludes the intended maximum value, and the fix using hi directly is accurate and straightforward.

Medium
## PR Code Suggestions ✨ <!-- be281ab --> Explore these optional code suggestions: <table><thead><tr><td><strong>Category</strong></td><td align=left><strong>Suggestion&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </strong></td><td align=center><strong>Impact</strong></td></tr><tbody><tr><td rowspan=3>Possible issue</td> <td> <details><summary>Fix off-by-one and divide-by-zero bug</summary> ___ **The divisor should be <code>b</code>, not <code>b - 1</code>. Using <code>b - 1</code> introduces an off-by-one error and <br>causes a divide-by-zero when <code>b == 1</code>. Additionally, a guard for <code>b == 0</code> should be <br>added to prevent a <code>ZeroDivisionError</code>.** [divider.py [3]](https://git.bzz.bz/rimskij/pr-agent-test/src/branch/fix/off-by-one/divider.py#L3-L3) ```diff -return a / (b - 1) # off-by-one: should be just b +if b == 0: + raise ValueError("Division by zero") +return a / b ``` <details><summary>Suggestion importance[1-10]: 9</summary> __ Why: Correctly identifies two bugs: the `b - 1` off-by-one error and the missing zero-division guard. The improved code properly fixes both issues. </details></details></td><td align=center>High </td></tr><tr><td> <details><summary>Fix off-by-one in average calculation</summary> ___ **<code>values[:-1]</code> excludes the last element before summing, producing an incorrect <br>average. The sum should be computed over the full <code>values</code> list. Also, a guard against <br>empty lists should be added to avoid divide-by-zero.** [divider.py [7]](https://git.bzz.bz/rimskij/pr-agent-test/src/branch/fix/off-by-one/divider.py#L7-L7) ```diff -return sum(values[:-1]) / len(values) +if not values: + raise ValueError("Cannot average an empty list") +return sum(values) / len(values) ``` <details><summary>Suggestion importance[1-10]: 9</summary> __ Why: Correctly identifies that `values[:-1]` drops the last element causing an incorrect average, and the fix using `sum(values)` is accurate. The empty list guard is a good addition. </details></details></td><td align=center>High </td></tr><tr><td> <details><summary>Fix off-by-one in upper bound clamp</summary> ___ **Using <code>hi - 1</code> as the upper bound incorrectly excludes the intended maximum value <code>hi</code>. <br>The clamp should use <code>hi</code> directly so that <code>v</code> can reach the full upper bound.** [divider.py [15]](https://git.bzz.bz/rimskij/pr-agent-test/src/branch/fix/off-by-one/divider.py#L15-L15) ```diff -return max(lo, min(v, hi - 1)) +return max(lo, min(v, hi)) ``` <details><summary>Suggestion importance[1-10]: 8</summary> __ Why: Correctly identifies that `hi - 1` incorrectly excludes the intended maximum value, and the fix using `hi` directly is accurate and straightforward. </details></details></td><td align=center>Medium </td></tr></tr></tbody></table>
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin fix/off-by-one:fix/off-by-one
git switch fix/off-by-one

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff fix/off-by-one
git switch fix/off-by-one
git rebase main
git switch main
git merge --ff-only fix/off-by-one
git switch fix/off-by-one
git rebase main
git switch main
git merge --no-ff fix/off-by-one
git switch main
git merge --squash fix/off-by-one
git switch main
git merge --ff-only fix/off-by-one
git switch main
git merge fix/off-by-one
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
rimskij/pr-agent-test!1
No description provided.