Skip to content

Conversation

roidelapluie
Copy link
Member

Split unary operator handling in duration expressions into two specific cases to fix precedence conflicts:

  • Handle unary operators with number literals directly
  • Handle unary operators with parenthesized expressions separately

This prevents unary minus from incorrectly binding to subsequent operators in expressions like foo offset -1^1, ensuring it parses as (foo offset -1) ^ 1 rather than foo offset (-1^1).

Fixes #16711

@roidelapluie roidelapluie marked this pull request as draft June 10, 2025 14:58
@roidelapluie

This comment was marked as outdated.

@roidelapluie roidelapluie force-pushed the fix-pow-dur-expr branch 2 times, most recently from 0d1e0b7 to 2943a85 Compare June 13, 2025 10:01
@roidelapluie roidelapluie marked this pull request as ready for review June 13, 2025 11:27
Split unary operator handling in duration expressions into two specific
cases to fix precedence conflicts:
- Handle unary operators with number literals directly
- Handle unary operators with parenthesized expressions separately

This prevents unary minus from incorrectly binding to subsequent
operators in expressions like `foo offset -1^1`, ensuring it parses
as `(foo offset -1) ^ 1` rather than `foo offset (-1^1)`.

Fixes prometheus#16711

Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
@roidelapluie roidelapluie requested a review from beorn7 June 13, 2025 13:09
@beorn7 beorn7 requested a review from krajorama June 14, 2025 22:33
@beorn7
Copy link
Member

beorn7 commented Jun 14, 2025

Will have a look ASAP, but @krajorama is probably way more qualified for this anyway.

Copy link
Contributor

@MichaHoffmann MichaHoffmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! this also fixes a crash in the parser related to offset arithmetic on this expression:

    avg(
              {__name__="http_requests_total",route!="/"} offset -1m
            ^
              {__name__="http_requests_total",route!="/"}
    )

which crashes without this commit on

time=2025-06-15T09:13:36.500Z level=INFO source=manager.go:176 msg="Starting rule manager..." component="rule manager"
parser panic: runtime error: index out of range [0] with length 0
goroutine 722 [running]:
github.com/prometheus/prometheus/promql/parser.(*parser).recover(0xc0004b2fc0?, 0xc001574968)
	/home/mhoffmann/git/upstream/prometheus/promql/parser/parse.go:343 +0x99
panic({0x3cb8000?, 0xc001680270?})
	/nix/store/02kl9hh07rl3iyvsdrcrhgq7xzi0wf2w-go-1.23.8/share/go/src/runtime/panic.go:791 +0x132
github.com/prometheus/prometheus/promql/parser.(*parser).newAggregateExpr(0xc000a78608?, {0x40583f9?, 0xb?, {0xc00156c005?, 0x0?}}, {0x46bcc20?, 0xc000102ae0?}, {0x46bcd40?, 0xc001574878?})
	/home/mhoffmann/git/upstream/prometheus/promql/parser/parse.go:456 +0x354
github.com/prometheus/prometheus/promql/parser.(*yyParserImpl).Parse(0xc000a786a8, {0x46a4fe0, 0xc000a78608})

but works fine on this branch!

Copy link
Member

@krajorama krajorama left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. I'd add something in the doc https://prometheus.io/docs/prometheus/latest/feature_flags/#promql-arithmetic-expressions-in-time-durations about this case and mention that if in doubt use ().

Signed-off-by: Julien Pivotto <291750+roidelapluie@users.noreply.github.com>
@roidelapluie roidelapluie enabled auto-merge June 16, 2025 09:12
@roidelapluie roidelapluie merged commit 998840c into prometheus:main Jun 16, 2025
27 checks passed
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.

PromQL: parser has wrong precedence with unary + and -, affecting offset arithmetic
4 participants