这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@Icenowy
Copy link
Contributor

@Icenowy Icenowy commented Mar 24, 2025

The chunkset_tpl comment allows negative dist (out - from) as long as the length is smaller than the absolute value of dist (i.e. memory does not overlap). However this case is currently broken in the RVV override of CHUNKCOPY -- it compares dist (which is a ptrdiff_t, a value that should be of the same size with size_t but signed) with the result of sizeof (which is a size_t), and this triggers the implicit conversion from signed to unsigned (thus losing negative values).

As it's promised to be not overlapping when dist is negative, just use a gaint memcpy() call to copy everything.

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced error handling for memory copy operations, allowing better management of pointer overlap scenarios.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 24, 2025

Walkthrough

The changes update the CHUNKCOPY function in the RISC-V architecture code. The if-statement condition was modified from if (dist >= len) to if (dist < 0 || dist >= len), thereby including cases where the out pointer is positioned before the from pointer. The change ensures that a memcpy operation is executed when either the pointer distance is negative or exceeds the length. The remainder of the function’s operations remains unchanged.

Changes

File(s) Change Summary
arch/riscv/chunkset_rvv.c Modified the pointer distance check in the CHUNKCOPY function to include negative distances.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant CHUNKCOPY
    participant memcpy
    Caller->>CHUNKCOPY: Call CHUNKCOPY(out, from, len)
    CHUNKCOPY->>CHUNKCOPY: Compute dist = out - from
    alt dist < 0 or dist >= len
        CHUNKCOPY->>memcpy: Execute memcpy(out, from, len)
    else
        CHUNKCOPY->>CHUNKCOPY: Handle overlapping copy scenario
    end
    CHUNKCOPY->>Caller: Return result
Loading

Possibly related PRs

Suggested labels

bug

Suggested reviewers

  • KungFuJesus
  • Dead2

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between db46081 and 1b3a2c2.

📒 Files selected for processing (1)
  • arch/riscv/chunkset_rvv.c (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • arch/riscv/chunkset_rvv.c
⏰ Context from checks skipped due to timeout of 90000ms (59)
  • GitHub Check: Windows MSVC 2022 v142 Win64
  • GitHub Check: Ubuntu GCC PPC64LE
  • GitHub Check: Ubuntu GCC ASAN
  • GitHub Check: macOS GCC Symbol Prefix & Compat (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix
  • GitHub Check: Windows MSVC 2022 v142 Win64
  • GitHub Check: Ubuntu GCC PPC64LE
  • GitHub Check: Ubuntu GCC ASAN
  • GitHub Check: macOS GCC (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix & Compat (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix
  • GitHub Check: Windows MSVC 2022 v142 Win64
  • GitHub Check: Ubuntu GCC PPC64LE
  • GitHub Check: Ubuntu GCC ASAN
  • GitHub Check: macOS GCC (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix & Compat (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix
  • GitHub Check: Windows MSVC 2022 v142 Win64
  • GitHub Check: Ubuntu GCC PPC64LE
  • GitHub Check: Ubuntu GCC ASAN
  • GitHub Check: macOS GCC (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix & Compat (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix
  • GitHub Check: Windows MSVC 2022 v142 Win64
  • GitHub Check: Ubuntu GCC PPC64LE
  • GitHub Check: Ubuntu GCC ASAN
  • GitHub Check: macOS GCC (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix & Compat (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix
  • GitHub Check: Windows MSVC 2022 v142 Win64
  • GitHub Check: Ubuntu GCC PPC64LE
  • GitHub Check: Ubuntu GCC ASAN
  • GitHub Check: macOS GCC (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix & Compat (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix
  • GitHub Check: Windows MSVC 2022 v142 Win64
  • GitHub Check: Ubuntu GCC PPC64LE
  • GitHub Check: Ubuntu GCC ASAN
  • GitHub Check: macOS GCC (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix & Compat (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix
  • GitHub Check: Windows MSVC 2022 v142 Win64
  • GitHub Check: Ubuntu GCC PPC64LE
  • GitHub Check: Ubuntu GCC ASAN
  • GitHub Check: macOS GCC (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix & Compat (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix
  • GitHub Check: Windows MSVC 2022 v142 Win64
  • GitHub Check: Ubuntu GCC PPC64LE
  • GitHub Check: Ubuntu GCC ASAN
  • GitHub Check: macOS GCC (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix & Compat (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix
  • GitHub Check: Windows MSVC 2022 v142 Win64
  • GitHub Check: Ubuntu GCC PPC64LE
  • GitHub Check: Ubuntu GCC ASAN
  • GitHub Check: macOS GCC (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix & Compat (ARM64)
  • GitHub Check: macOS GCC Symbol Prefix

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • 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. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

Documentation and Community

  • 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.

@codecov
Copy link

codecov bot commented Mar 24, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 82.74%. Comparing base (64d16e1) to head (1b3a2c2).
Report is 3 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff              @@
##           develop    #1889       +/-   ##
============================================
+ Coverage    42.20%   82.74%   +40.54%     
============================================
  Files           71      143       +72     
  Lines         7353    12510     +5157     
  Branches      1265     2845     +1580     
============================================
+ Hits          3103    10352     +7249     
+ Misses        4016     1209     -2807     
- Partials       234      949      +715     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@KungFuJesus
Copy link
Contributor

I will say, I don't think it's expected for chunkcopy to ever get a from pointer from which it can't read at least a chunk's worth of bytes. Whether that is from behind or in front of out shouldn't actually matter, we gate whether or not chunk copy is called from the outside based on the distance and whether or not they are at least chunk_t sizes apart.

We leverage chunk_memset more in the manner you're handling here, where negative distances are handled by a single memmove (we do in fact have negative distances for chunk_memset that can overlap). Everywhere you see a chunked copy operation, it's a surrogate for the copy idiom of a self modifying copy, a byte a time as in *to++ = *from++. When this is done with to behind from, it is effectively the same thing as a memmove (where the contents slide down).

@Icenowy
Copy link
Contributor Author

Icenowy commented Mar 25, 2025

@KungFuJesus Well the reason for the SIGSEGV is quite simple, but a little implicit to non-language-lawyers -- later in the function, it's comparing a (possibly) negative value typed ptrdiff_t (which should be of the same size with size_t, but signed) with the result of sizeof (which is a size_t), that triggers the promote of signed value to unsigned and converting a negative value to a huge unsigned value, which makes dist >= sizeof(chunk_t) true for negative values (which is unexpected). Then dist is passed to memcpy(), which expects an unsigned value, and the negative value gets interpreted as copying nearly the whole address space -- it will surely fail.

BTW I think the problem of RVV CHUNKCOPY is only exhibited after chunk_memset is refactored (which I bisected to).

@nmoinvaz nmoinvaz added the Architecture Architecture specific label Mar 25, 2025
@Icenowy
Copy link
Contributor Author

Icenowy commented Mar 26, 2025

Ping because this is a big issue that renders zlib-ng nearly totally unfunctional (and 2.2.3/2.2.4 releases are broken).

@KungFuJesus
Copy link
Contributor

KungFuJesus commented Mar 26, 2025

Have you isolated the issue to be RISC-V specific? I guess my main concern is whether or not it's a wider issue and you just have a dataset invoking the error before. What's weird to me is the fact that RISCV's chunkcopy implementation has to take into account the distance at all. That's something we are deferring to chunkmemset et al elsewhere to determine whether or not chunkcopy should be called.

Do you know the line calling it where it's a problem? The templated chunkmemset should be handling these scenarios.

Ahh, it looks like at least part of the issue stems from the fact that this variant tries to maximize how many chunks can be copied with the distance and passes it all to memcpy at once, rather than having a loop that does chunk bytes for the entirety of it. That does require determining the distance between the two. Perhaps something was dispatching to the libc function with memcpy and this was to avoid that.

Now it makes some sense to me why this is affected and nothing else. The bigger change with that refactor is that we call chunkcopy in more opportunities. Most of the time chunkcopy doesn't have to care if the source is behind or in front of the destination.

@Icenowy
Copy link
Contributor Author

Icenowy commented Mar 26, 2025

This is surely a RISC-V specific issue because only RISC-V has a specialized implementation of CHUNKCOPY (others all uses the on in the template header). I was going to remove the override of CHUNKCOPY in #1888 but it seems that at least some people isn't fond of this.

@Icenowy
Copy link
Contributor Author

Icenowy commented Mar 26, 2025

@KungFuJesus so is the comment in chunkset_tpl.h before the standard implementation of CHUNKCOPY still correct and accurate?

BTW I think the whole RVV optimized chunkset implementation relies on compiler unrolling memcpy -- the code contains memcpy's but no RVV intrinsics, even in chunk load/store functions.

@Icenowy
Copy link
Contributor Author

Icenowy commented Mar 26, 2025

BTW #1890 fixes the CI of RISC-V and correctly exhibits the problem solved in this PR.

@KungFuJesus
Copy link
Contributor

@KungFuJesus so is the comment in chunkset_tpl.h before the standard implementation of CHUNKCOPY still correct and accurate?

BTW I think the whole RVV optimized chunkset implementation relies on compiler unrolling memcpy -- the code contains memcpy's but no RVV intrinsics, even in chunk load/store functions.

Yes, CHUNKCOPY from the templates is only ever called if there's at least sizeof(chunk_t)'s worth of bytes between them. On everything but AVX512 we also only call CHUNKCOPY when it's safe to over write past len by a chunk_t in the destination buffer. With AVX512 we mitigate having to worry about all that by leveraging masked writes.

Copy link
Member

@Dead2 Dead2 left a comment

Choose a reason for hiding this comment

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

LGTM

The chunkset_tpl comment allows negative dist (out - from) as long as
the length is smaller than the absolute value of dist (i.e. memory does
not overlap). However this case is currently broken in the RVV override
of CHUNKCOPY -- it compares dist (which is a ptrdiff_t, a value that
should be of the same size with size_t but signed) with the result of
sizeof (which is a size_t), and this triggers the implicit conversion
from signed to unsigned (thus losing negative values).

As it's promised to be not overlapping when dist is negative, just use a
gaint memcpy() call to copy everything.

Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
@Icenowy Icenowy force-pushed the rvv-sigsegv-fix-chunkcopy branch from db46081 to 1b3a2c2 Compare March 28, 2025 05:30
@Dead2 Dead2 merged commit 2bba7e8 into zlib-ng:develop Mar 28, 2025
147 of 152 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Architecture Architecture specific

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants