Files
bun.sh/test/regression/issue/22475.test.ts
robobun 5b842ade1d Fix cookie.isExpired() returning false for Unix epoch (#22478)
## Summary
Fixes #22475 

`cookie.isExpired()` was incorrectly returning `false` for cookies with
`Expires` set to Unix epoch (Thu, 01 Jan 1970 00:00:00 GMT).

## The Problem
The bug had two parts:

1. **In `Cookie::isExpired()`**: The condition `m_expires < 1`
incorrectly treated Unix epoch (0) as a session cookie instead of an
expired cookie.

2. **In `Cookie::parse()`**: When parsing date strings that evaluate to
0 (Unix epoch), the code used implicit boolean conversion which treated
0 as false, preventing the expires value from being set.

## The Fix
- Removed the `m_expires < 1` check from `isExpired()`, keeping only the
check for `emptyExpiresAtValue` to identify session cookies
- Fixed date parsing to use `std::isfinite()` instead of implicit
boolean conversion, properly handling Unix epoch (0)

## Test Plan
- Added regression test in `test/regression/issue/22475.test.ts`
covering Unix epoch and edge cases
- All existing cookie tests pass (`bun bd test test/js/bun/cookie/`)
- Manually tested the reported issue from #22475

```javascript
const cookies = [
  'a=; Expires=Thu, 01 Jan 1970 00:00:00 GMT',
  'b=; Expires=Thu, 01 Jan 1970 00:00:01 GMT'
];

for (const _cookie of cookies) {
  const cookie = new Bun.Cookie(_cookie);
  console.log(cookie.name, cookie.expires, cookie.isExpired());
}
```

Now correctly outputs:
```
a 1970-01-01T00:00:00.000Z true
b 1970-01-01T00:00:01.000Z true
```

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2025-09-07 17:42:09 -07:00

51 lines
1.9 KiB
TypeScript

import { expect, test } from "bun:test";
test("issue #22475: cookie.isExpired() should return true for Unix epoch (0)", () => {
const cookies = ["a=; Expires=Thu, 01 Jan 1970 00:00:00 GMT", "b=; Expires=Thu, 01 Jan 1970 00:00:01 GMT"];
const results = [];
for (const _cookie of cookies) {
const cookie = new Bun.Cookie(_cookie);
results.push({
name: cookie.name,
expires: cookie.expires,
isExpired: cookie.isExpired(),
});
}
// Cookie 'a' with Unix epoch (0) should be expired
expect(results[0].name).toBe("a");
expect(results[0].expires).toBeDate();
expect(results[0].expires?.getTime()).toBe(0);
expect(results[0].isExpired).toBe(true);
// Cookie 'b' with 1 second after Unix epoch should also be expired
expect(results[1].name).toBe("b");
expect(results[1].expires).toBeDate();
expect(results[1].expires?.getTime()).toBe(1000);
expect(results[1].isExpired).toBe(true);
});
test("cookie.isExpired() for various edge cases", () => {
// Test Unix epoch (0) - should be expired
const epochCookie = new Bun.Cookie("test", "value", { expires: 0 });
expect(epochCookie.expires).toBeDate();
expect(epochCookie.expires?.getTime()).toBe(0);
expect(epochCookie.isExpired()).toBe(true);
// Test negative timestamp - should be expired
const negativeCookie = new Bun.Cookie("test", "value", { expires: -1 });
expect(negativeCookie.expires).toBeDate();
expect(negativeCookie.expires?.getTime()).toBe(-1000);
expect(negativeCookie.isExpired()).toBe(true);
// Test session cookie (no expires) - should not be expired
const sessionCookie = new Bun.Cookie("test", "value");
expect(sessionCookie.expires).toBeUndefined();
expect(sessionCookie.isExpired()).toBe(false);
// Test future date - should not be expired
const futureCookie = new Bun.Cookie("test", "value", { expires: Date.now() + 86400000 });
expect(futureCookie.isExpired()).toBe(false);
});