pingcap / pingcap/tidb

br: --backupts accepts future timestamps without validation

Open
#66,280 2 comments 0 reactions 0 assignees View on GitHub
component/br needs-cherry-pick-release-6.5 severity/moderate type/bug
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)

```bash
# Using datetime format with a future timestamp
br backup full --pd "127.0.0.1:2379" --storage "local:///tmp/backup" --backupts "2099-12-31 23:59:59+0800"

# Or using a very large TSO-like number representing future time
br backup full --pd "127.0.0.1:2379" --storage "local:///tmp/backup" --backupts "999999999999999999"
```

### 2. What did you expect to see? (Required)

BR should reject the backup request with a clear error message:
```
Error: invalid backup timestamp: timestamp cannot be in the future (specified: 2099-12-31 23:59:59, current: 2026-02-14 15:30:00)
```

### 3. What did you see instead (Required)

BR accepts the future timestamp without validation. The backup operation proceeds without error, which is incorrect behavior because:
- Point-in-time backup should only work for past timestamps
- Future timestamps are semantically invalid for backup operations
- Users receive no feedback that they have provided an invalid parameter

### 4. What is your TiDB version? (Required)

**Affected versions:**
- TiDB v6.5.3
- Current master branch (commit: d7ce2f2faa)

### Root Cause Analysis

The validation logic has two gaps:

**1. In ParseTSString() function** (\`br/pkg/task/backup.go\` lines 789-814):
- Parses timestamp strings (both TSO and datetime formats)
- Converts to uint64 timestamp
- **Missing:** No check against current time

**2. In GetTS() function** (\`br/pkg/backup/client.go\` lines 458-497):
- Validates timestamp is not before GC safepoint (line 493)
- **Missing:** No check that timestamp is not in the future

### Code References

**Current validation (only checks GC safepoint):**
```go
// br/pkg/backup/client.go:492-496
// check backup time do not exceed GCSafePoint
err = gc.CheckGCSafePoint(ctx, bc.mgr.GetGCManager(), backupTS)
if err != nil {
return 0, errors.Trace(err)
}
```

**Flag definition:**
```go
// br/pkg/task/backup.go:119-120
flags.String(flagBackupTS, "", "the backup ts support TSO or datetime,"+
" e.g. '400036290571534337', '2018-05-11 01:42:23'")
```

### Proposed Solution

Add future timestamp validation in GetTS() function after the user-provided timestamp is set but before GC safepoint check:

**Location:** \`br/pkg/backup/client.go\` around line 470

```go
if ts > 0 {
backupTS = ts

// Validate timestamp is not in the future
p, l, err := bc.mgr.GetPDClient().GetTS(ctx)
if err != nil {
return 0, errors.Trace(err)
}
currentTS := oracle.ComposeTS(p, l)
if backupTS > currentTS {
return 0, errors.Annotatef(berrors.ErrInvalidArgument,
"backup timestamp cannot be in the future")
}
} else {
// ... existing code for getting current timestamp
}
```

### Related Issues

Part of tracking issue: #66279

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.