see https://issues.apache.org/bugzilla/show_bug.cgi?id=44262
The docs for 2.0 say about AllowOverride Options: (http://httpd.apache.org/docs/2.0/mod/core.html#allowoverride) " Options Allow use of the directives controlling specific directory features (Options and XBitHack). " and for 2.2 (http://httpd.apache.org/docs/2.2/mod/core.html#allowoverride) " Options[=Option,...]Allow use of the directives controlling specific directory features (Options and XBitHack). An equal sign may be given followed by a comma (but no spaces) separated lists of options that may be set using the Options command. " In 2.0 they don't specify which Options can be overwritten and in 2.2 =Option,.. is optional so I expect Options without =Option,... be compatible with old AllowOverride Options. The catch is that Option All isn't really all the options. from includes/http_core.h " /** No directives */ #define OPT_NONE 0 /** Indexes directive */ #define OPT_INDEXES 1 /** Includes directive */ #define OPT_INCLUDES 2 /** FollowSymLinks directive */ #define OPT_SYM_LINKS 4 /** ExecCGI directive */ #define OPT_EXECCGI 8 /** directive unset */ #define OPT_UNSET 16 /** IncludesNOEXEC directive */ #define OPT_INCNOEXEC 32 /** SymLinksIfOwnerMatch directive */ #define OPT_SYM_OWNER 64 /** MultiViews directive */ #define OPT_MULTI 128 /** All directives */ #define OPT_ALL (OPT_INDEXES | OPT_INCLUDES | OPT_SYM_LINKS | OPT_EXECCGI) " so OPT_INCNOEXEC OPT_SYM_OWNER OPT_MULTI are omitted from All. in 2.2.x AllowOverride Options= allows everything including Multiviews and others AllowOverride Options allows only All and this is only OPT_INDEXES | OPT_INCLUDES | OPT_SYM_LINKS | OPT_EXECCGI The bug is in server/core.c:1286 l is the string after "Options=", in this case its just an empty string. static const char *set_allow_opts(cmd_parms *cmd, allow_options_t *opts, const char *l) { allow_options_t opt; int first = 1; char *w, *p = (char *) l; char *tok_state; while ((w = apr_strtok(p, ",", &tok_state)) != NULL) { if (first) { p = NULL; *opts = OPT_NONE; first = 0; } if (!strcasecmp(w, "Indexes")) { opt = OPT_INDEXES; } else if (!strcasecmp(w, "Includes")) { opt = OPT_INCLUDES; } ... else if (!strcasecmp(w, "None")) { opt = OPT_NONE; } else if (!strcasecmp(w, "All")) { opt = OPT_ALL; } else { return apr_pstrcat(cmd->pool, "Illegal option ", w, NULL); } *opts |= opt; } (*opts) &= (~OPT_UNSET); return NULL; } In case of Options= the while loop isn't executed and options are set to (*opts) &= (~OPT_UNSET); which is previous options & 0xffffffff . Probably in case if OPT_UNSET is not 0. opts by default are server/core.c:99 static void *create_core_dir_config(apr_pool_t *a, char *dir) ... conf->override_opts = OPT_UNSET | OPT_ALL | OPT_INCNOEXEC | OPT_SYM_OWNER | OPT_MULTI; and in server/core.c set_override() .. d->override = OR_NONE; while (l[0]) { w = ap_getword_conf(cmd->pool, &l); k = w; v = strchr(k, '='); if (v) { *v++ = '\0'; } if (!strcasecmp(w, "Limit")) { d->override |= OR_LIMIT; } else if (!strcasecmp(k, "Options")) { // in case of Options= v="" d->override |= OR_OPTIONS; if (v) //in case of "AllowOverride Options=" set_allow_opts() leavs d->override_opts unchanged set_allow_opts(cmd, &(d->override_opts), v); else // in case of "AllowOverride Options" sets ONLY!!! OPT_ALL ommiting OPT_MULTIVIEWS and others d->override_opts = OPT_ALL; This is at least inconsistent, Options= should be a syntax error, or OPT_NONE + warning. In pre Options= releases (it bit me hard when I upgraded to 2.2.8 from 2.0.61) AllovOverride Options allowed overriding any options not only those in OPT_ALL, and now suddenly it stopped but allowed old behavior if I set AllowOverride Options=. We might even call it an regression because old correct config (new docs don't mention any changes so I expect new versions to be compatible) stops to work. I will produce a patch when it get's decided what to do with an empty "Options=" (in docs defined as Options[=Option,] so there must be at least 1 option set) -- Michał Grzędzicki