Skip to content

Conversation

@faratech
Copy link

@faratech faratech commented Dec 26, 2025

Summary

This PR adds a complete Rust port of ddate.

Note: This should ideally be merged into a new rust branch rather than master, to keep the Rust implementation separate from the C version. Please consider creating a rust branch and retargeting this PR.


  • stdlib only - no external crates, pure Rust
  • Exact compatibility - byte-for-byte identical output to C version
  • Cargo features for compile-time configuration:
    • old_immediate_fmt (default) - original immediate mode format
    • kill_bob (default) - X-Day countdown support
    • us_format - US date format (m-d-y)
    • praise_bob - SubGenius slogans
  • Optimized for size - opt-level = "z", LTO, panic=abort, strip
  • Memory safe - no buffer overflows possible (addresses the vulnerability in the C version)

File structure

src/
├── main.rs         # Entry point, CLI parsing
├── disc_time.rs    # DiscTime struct, convert(), makeday()
├── format.rs       # Format string parser
├── constants.rs    # All string constants
└── random.rs       # LCG PRNG matching glibc rand()
Cargo.toml
Makefile            # Build with optional UPX compression

Building

cargo build --release
# Or with UPX compression:
make release

Binary size

  • C version: ~67KB (stripped)
  • Rust version: ~325KB → ~148KB with UPX

Test plan

  • Verified identical output for various dates
  • Tested St. Tib's Day (Feb 29 on leap years)
  • Tested all format specifiers
  • Tested holiday detection
  • Verified feature flags work correctly

Fully compatible reimplementation in Rust with:
- Byte-for-byte output compatibility with C version
- All format specifiers: %A %a %B %b %d %e %H %N %n %t %Y %X %. %{ %}
- Cargo features: old_immediate_fmt, us_format, kill_bob, praise_bob
- Makefile with UPX compression (147KB vs 67KB C)

Fixes buffer overflow vulnerability in C version where user-controlled
format strings can overflow the fixed 391-byte output buffer.
@danwdart
Copy link
Collaborator

I have no objections against having different language ports, but I fear that their features would all differ and especially with all the options that are coming in with the C version, and personally I'd have made a Haskell port after the new features coming in.

I feel like it's up to the people who better understand Rust to maintain that one and then if they decide to disappear, it may be confusing for the C heads here.

As far as how far this would get - I would probably be cool with that being a fork perhaps? Would distributions make it a different package? A different version (or suffix version)?

I'm not completely against just keeping it in a branch and assigning permissions to the branch, or just keeping it in a separate repo managed by someone else.

@faratech
Copy link
Author

It has worked well since 1993, I was just testing - could always just keep it up as a fork. The C version is actually smaller in size and the buffer overflow was fixed!

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.

2 participants