Repository: VictoriaMetrics/VictoriaMetrics
Pull request #4539 (2023-06-29 11:11:18)

fix parse for invalid partial RFC3339 format
Unlike prometheus, VictoriaMetrics accepts [format timestamp with four letter as year](https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#timestamp-formats) in [query APIs](https://docs.victoriametrics.com/#prometheus-querying-api-usage) and in [export APIs](https://docs.victoriametrics.com/#how-to-export-time-series).
We parse time using time.UnixNano which can only store maxInt64, so the valid year is between [1970,2262]

tip: User can't query data by passing timestamp "6000" as "1970-10-01 00:10:00" like prometheus, they should use something like 1970-01-01T10:00:00.


Haleygo: @hagen1778 
So the reason of missing query result under 10000 is found, I will set the startTime in my test to 10000 instead of 0.

Patch:
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index e7e9ffdae..314d199c3 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -42,7 +42,7 @@ The following tip changes can be tested by building VictoriaMetrics components f
   `--search.maxGraphiteTagValues` for limiting the number of tag values returned Graphite `/tags/<tag_name>` API. 
   Remove redundant limit from [Prometheus api/v1/series](https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#prometheus-querying-api-usage). See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/4339).
 * BUGFIX: [vmui](https://docs.victoriametrics.com/#vmui): fix application routing issues and problems with manual URL changes. See [this pull request](https://github.com/VictoriaMetrics/VictoriaMetrics/pull/4408).
-
+* BUGFIX: add validation for invalid [partial RFC3339 timestamp formats](https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#timestamp-formats) in query and export APIs.
 
 ## [v1.91.3](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.91.3)
 
diff --git a/lib/promutils/time.go b/lib/promutils/time.go
index 1f644ef40..5b999c27f 100644
--- a/lib/promutils/time.go
+++ b/lib/promutils/time.go
@@ -17,6 +17,12 @@ func ParseTime(s string) (float64, error) {
 	return ParseTimeAt(s, currentTimestamp)
 }
 
+const (
+	// time.UnixNano can only store maxInt64, which is 2262
+	maxValidYear = 2262
+	minValidYear = 1970
+)
+
 // ParseTimeAt parses time s in different formats, assuming the given currentTimestamp.
 //
 // See https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#timestamp-formats
@@ -67,6 +73,10 @@ func ParseTimeAt(s string, currentTimestamp float64) (float64, error) {
 		if err != nil {
 			return 0, err
 		}
+		y := t.Year()
+		if y > maxValidYear || y < minValidYear {
+			return 0, fmt.Errorf("cannot parse year from %q: year must in range [%d, %d]", s, minValidYear, maxValidYear)
+		}
 		return tzOffset + float64(t.UnixNano())/1e9, nil
 	}
 	if !strings.Contains(sOrig, "-") {


Test patch:
diff --git a/lib/promutils/time_test.go b/lib/promutils/time_test.go
index cb311348d..38934eea4 100644
--- a/lib/promutils/time_test.go
+++ b/lib/promutils/time_test.go
@@ -91,6 +91,7 @@ func TestParseTimeFailure(t *testing.T) {
 	}
 
 	f("")
+	f("2263")
 	f("23-45:50")
 	f("1223-fo:ba")
 	f("1223-12:ba")