Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 37 additions & 23 deletions .github/workflows/testsuite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- run: perl -V
- name: install dependencies
uses: perl-actions/install-with-cpm@v1
uses: perl-actions/install-with-cpm@stable
with:
cpanfile: "cpanfile"
- name: Makefile.PL
Expand All @@ -35,9 +35,7 @@ jobs:
needs: [ubuntu]
env:
PERL_USE_UNSAFE_INC: 0
AUTHOR_TESTING: 1
AUTOMATED_TESTING: 1
RELEASE_TESTING: 1

runs-on: ubuntu-latest

Expand All @@ -46,6 +44,10 @@ jobs:
matrix:
perl-version:
[
"5.40",
"5.38",
"5.36",
"5.34",
"5.32",
"5.30",
"5.28",
Expand All @@ -58,48 +60,60 @@ jobs:
"5.14",
"5.12",
"5.10",
"5.8",
]

container:
image: perl:${{ matrix.perl-version }}

steps:
- uses: actions/checkout@v2
- run: perl -V
- name: install dependencies
uses: perl-actions/install-with-cpm@v1
- uses: actions/checkout@v4
- name: Set up perl ${{ matrix.perl-version }}
uses: shogo82148/actions-setup-perl@v1
with:
sudo: false
cpanfile: "cpanfile"
perl-version: ${{ matrix.perl-version }}
- run: perl -V
- name: Makefile.PL
run: perl -I$(pwd) Makefile.PL
- name: make
run: make
- name: make test
run: make test

macOS:
needs: [ubuntu]
env:
PERL_USE_UNSAFE_INC: 0
AUTHOR_TESTING: 1
AUTOMATED_TESTING: 1
RELEASE_TESTING: 1

runs-on: macOS-latest

strategy:
fail-fast: false
matrix:
perl-version: [latest]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- run: perl -V
- name: install dependencies
uses: perl-actions/install-with-cpm@v1
uses: perl-actions/install-with-cpm@stable
with:
cpanfile: "cpanfile"
- name: Makefile.PL
run: perl -I$(pwd) Makefile.PL
- name: make test
run: make test

windows:
needs: [ubuntu]
env:
PERL_USE_UNSAFE_INC: 0
AUTOMATED_TESTING: 1

runs-on: windows-latest

steps:
- uses: actions/checkout@v4
- name: Set up Strawberry Perl
uses: shogo82148/actions-setup-perl@v1
with:
perl-version: "5.38"
- run: perl -V
- name: Makefile.PL
run: perl Makefile.PL
- name: make
run: gmake
- name: make test
run: gmake test
102 changes: 102 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# CLAUDE.md — Digest::MD5

## Project identity

Digest::MD5 is a **dual-life** Perl module — it ships with perl core and is also released independently to CPAN. The canonical upstream is `gisle/digest-md5`. The `Dual-Life/Digest-MD5` fork is used for development; PRs target upstream.

- **Current version**: see `$VERSION` in `MD5.pm`
- **Minimum Perl**: 5.006 (declared in `Makefile.PL`)
- **XS module**: the core implementation is in `MD5.xs` (C code)

## Repository structure

```
MD5.pm Perl module (OO + functional interface, POD docs)
MD5.xs XS/C implementation of MD5 algorithm
Makefile.PL ExtUtils::MakeMaker build script
t/ Test suite
md5-aaa.t Exhaustive padding/correctness vectors (large, 549 lines)
files.t Checksums of README, MD5.xs, rfc1321.txt (hardcoded hashes!)
context.t context() save/restore tests
clone.t clone() method tests
utf8.t Unicode string handling
warns.t Warning detection for misuse patterns
align.t Unaligned memory block tests
badfile.t addfile() error handling
bits.t add_bits() method
threads.t Thread safety via ithread cloning
hints/ Platform-specific compiler workarounds (DEC, IRIX, MacOS)
bin/md5sum.pl Command-line md5sum utility
rfc1321.txt RFC 1321 reference text
```

## Build and test

```bash
perl Makefile.PL && make && make test
```

The XS code compiles to `MD5.c` -> `MD5.o` -> `blib/`. Always run `make test` before committing — a commit that doesn't pass tests is not a valid commit.

## What NOT to modify

- **Changes**: version history is maintained by the release manager, not contributors
- **Version numbers**: never bump `$VERSION` in `MD5.pm`
- **MANIFEST**: generated by `make manifest` — do not manually sort or reformat
- **README**: static file with hardcoded checksum in `t/files.t`

## Critical gotcha: t/files.t

`t/files.t` contains **hardcoded MD5 checksums** for `README`, `MD5.xs`, and `rfc1321.txt`. Any change to these three files will cause `files.t` to fail. When modifying `MD5.xs`, you **must** update the expected hash on line 25 of `t/files.t`:

```perl
# Update this hash after changing MD5.xs:
f4b5da4e0f19b4c0ab374b7085ed8955 MD5.xs
```

Compute the new hash with: `perl -MDigest::MD5 -e 'open my $f,"<","MD5.xs"; print Digest::MD5->new->addfile($f)->hexdigest'`

Or after rebuilding: `make test` will show the mismatch.

## XS code patterns

### Memory allocation
The codebase uses `New(id, ptr, n, type)` (deprecated) for allocations. The modern equivalent is `Newx(ptr, n, type)`. A compatibility shim exists for `Newxz` (line 48-49) but not yet for `Newx`.

### Endianness
`BYTEORDER` values differ between 32-bit (`0x1234`/`0x4321`) and 64-bit (`0x12345678`/`0x87654321`). The `TO32`/`TRUNC32` macros handle truncation when `BYTEORDER > 0x4321`. Any byte-swapping or endian-conditional code must handle both widths.

### 64-bit considerations
The MD5 byte counter uses split U32 fields (`bytes_low`/`bytes_high`). Carry detection compares against `STRLEN` (which is 64-bit on LP64 systems). Comparisons must use same-width operands to avoid implicit promotion bugs.

### Thread safety
When `USE_ITHREADS` and `MGf_DUP` are defined, the context is duplicated via `dup_md5_ctx()` on thread clone. The vtable structure differs between threaded and non-threaded builds.

## Test conventions

- Most tests use `Test::More` (converted from old `Test.pm` style)
- `files.t` still uses manual `print "ok"` / `print "not ok"` style
- `md5-aaa.t` is the comprehensive correctness test (88K, ~500 test vectors)
- Tests must handle `PERL_CORE` mode (some files unavailable when run from perl core build)
- `EBCDIC` paths exist in some tests for mainframe compatibility

## PR workflow

This repo (`Dual-Life/Digest-MD5`) is a **fork** of `gisle/digest-md5`.

- PRs go to upstream: `gh pr create --draft --repo gisle/digest-md5 --head Dual-Life:<branch>`
- Issues go to upstream: `gh issue create --repo gisle/digest-md5`
- Branch prefix: `koan.toddr.bot/`

## CI

GitHub Actions workflow in `.github/workflows/testsuite.yml`:
- Ubuntu (latest Perl), Linux matrix (5.8-5.32), macOS
- Uses `actions/checkout@v2` and `perl-actions/install-with-cpm@v1`
- Note: `.travis.yml` still exists but Travis CI is defunct for open source

## Open issues (as of 2025)

- **#10**: FIPS mode detection — MD5 should croak when system FIPS is enabled
- **#8**: U32 alignment on 64-bit — `BYTEORDER` conditionals need 64-bit values
- **#6**: Incorrect MD5 with large scalars — 64-bit byte counter overflow
1 change: 1 addition & 0 deletions MANIFEST.SKIP
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ pm_to_blib$
^cpanfile$
^\.gitignore$
^\.travis.yml$
^CLAUDE\.md$
^MYMETA\.
Loading