Bug 66374 - Error directive unintuitive when wrapped in <If>
Summary: Error directive unintuitive when wrapped in <If>
Status: REOPENED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: Core (show other bugs)
Version: 2.4.54
Hardware: PC Linux
: P2 normal (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-12-04 15:35 UTC by Michael Orlitzky
Modified: 2022-12-06 13:55 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Orlitzky 2022-12-04 15:35:27 UTC
After pulling most of my hair out, I've narrowed this down to the following hard-to-believe example in a vhost context:

  <If "'www' == 'x'">
    Error "www and x are equal"
  </If>

  # /etc/init.d/apache2 reload
   * apache2 has detected an error in your setup:
  AH00526: Syntax error...:
  www and x are equal

Wat?

I gather this has something to do with <If> being evaluated at runtime, but I think most people would agree that this example is absurd.
Comment 1 Eric Covener 2022-12-04 16:38:25 UTC
"Error" is for configuration problems that should interrupt parsing.

There is no short-circuiting of <if> config sections that can never evaluate to true during the processing of a request, the if and the directives they enclose are still part of the configuration.
Comment 2 Eric Covener 2022-12-04 17:19:01 UTC
Too hasty, maybe error can blow up when encountered in If
Comment 3 Eric Covener 2022-12-04 18:19:20 UTC
After more thought, it seems to be high risk/reward tradeoff to change the behavior here.  It marginally helps configs that don't startup today, but nesting <If>, IfDefine, and Error would be regressed.

I will leave it open for others to consider, but I suggest changing the subject or otherwise clarifying
Comment 4 Michael Orlitzky 2022-12-04 21:43:52 UTC
I think I'm having the same problem as bug #63146. There seems to be a lot of magic going on in the config parsing that interacts badly with <If>.

I don't really know what a good solution could look like given that I'm not an expert on the relevant limitations, but from a dumb user perspective (and to put it bluntly) it's pretty annoying to have a feature depend on secret details, and then fail silently / return bullshit / launch missiles when you run afoul of the rules you didn't know about.

If you asked 100 random programmers or system administrators what

  <If "'www' == 'x'">
    Error "www and x are equal"
  </If>

will do, I would be surprised if any of them guessed right. At a high level, my complaint is basically just that the actual behavior of <If> should more closely match the mental model of it that everyone is going to arrive with. And if that's not possible, throw a sensible error instead of quietly proceeding with a config that acts nothing like what is written.
Comment 5 Michael Orlitzky 2022-12-05 14:53:06 UTC
For posterity, this is a horrendous workaround for my original problem of comparing $host to "www":

  <IfDefine www>
    Error "Constant 'www' is already defined"
  </IfDefine>

  <IfDefine !$host>
    Define $host
    <IfDefine www>
      # Do whatever
    </IfDefine>
    Undefine $host
  </IfDefine>

I don't really recommend it, but it works in a pinch.
Comment 6 Joe Orton 2022-12-06 09:29:51 UTC
I agree we shouldn't change the behaviour. From a C perspective it's a bit like expecting

 if (0) {
#error fail
 }


to do compile as a noop. Maybe this could be clarified in the docs for Error/Warning.
Comment 7 Eric Covener 2022-12-06 13:42:54 UTC
changing subject.

added some warnings in 1905793
Comment 8 Michael Orlitzky 2022-12-06 13:46:32 UTC
My actual use case didn't involve Error, but ServerAlias. "Error" was just to obtain a minimal reproducible case. See bug #63146 for another real use case.

And as far as "Error" is concerned... the documentation includes the example,

  # ensure that exactly one of SSL,NOSSL is defined
  <IfDefine SSL>
  <IfDefine NOSSL>
    Error "Both SSL and NOSSL are defined.  Define only one of them."
  </IfDefine>
  </IfDefine>

which already implies that "Error" won't be executed if it's enclosed in a conditional that evaluates false. I don't think making the same assumption about <If> is too much of a stretch.

Regardless, the fundamental issue with <If> is that the user's config says one thing, but apache (quietly) ignores it and loads something else. In my case, either Error or ServerAlias get executed unconditionally, i.e. apache ignores the <If> entirely. In bug #63146, both Define statements that were intended to be mutually exclusive are executed.

I'm sure the technical details are a mess, but silently proceeding with a runtime config that (given what the user obviously intended) is so completely counter-intuituve is the worst possible failure mode for such a misconfiguation.
Comment 9 Eric Covener 2022-12-06 13:55:54 UTC
(In reply to Michael Orlitzky from comment #8)
> My actual use case didn't involve Error, but ServerAlias. "Error" was just
> to obtain a minimal reproducible case. See bug #63146 for another real use
> case.

For me ServerAlias inside of <If> always results in a startup failure as expected. It's not supported in any "directory" section which includes <if> already. But based on the defensive and histrionics in this report I'm not (personally) inclined to continue here.