Apache:重写规则导致segfault

Apache:重写规则导致segfault,apache,mod-rewrite,Apache,Mod Rewrite,我使用重写规则将URL中的所有空格(又名%20)替换为下划线: RewriteRule (.*)[\ ](.*) $1_$2 [N] [N]标志再次开始重写过程,直到没有剩余空间为止(希望如此)。现在,当有文件在另一端等待时,一切正常,即请求: /This is an example.html 和文件: This_is_an_example.html 但是,当没有匹配的文件时,Apache将退出,并出现500个内部错误。错误日志说明一个segfault,重写日志显示重写引擎在试图重定向到时

我使用重写规则将URL中的所有空格(又名%20)替换为下划线:

RewriteRule (.*)[\ ](.*) $1_$2 [N]
[N]标志再次开始重写过程,直到没有剩余空间为止(希望如此)。现在,当有文件在另一端等待时,一切正常,即请求:

/This is an example.html
和文件:

This_is_an_example.html
但是,当没有匹配的文件时,Apache将退出,并出现500个内部错误。错误日志说明一个segfault,重写日志显示重写引擎在试图重定向到时发疯

/This is an_example.html/This is an_example.html/This is an_example.html/...
以此类推,直到segfault(请注意,最后一个空间已转换,但没有其他空间)

有人知道为什么重写规则在处理现有文件时失败得如此惨重吗

更新:只有在请求的URI中有一个额外的“/”时,才会出现segfault,如

/virtual-directory/This is an example.html
更新2:此语句中没有重写条件。在我看来,它应该在没有任何限制的情况下起作用。问题是,为什么不呢。Htaccess:

RewriteEngine On
RewriteBase /test/

RewriteRule (.*)[\ ](.*) $1_$2 [N]
更新3:有问题的.htaccess文件:

AddType application/xhtml+xml .xhtml
AddEncoding x-gzip .gz

ExpiresActive On
ExpiresByType application/xhtml+xml "access plus 1 year"

ErrorDocument 404 /test/index.php?error=404

RewriteEngine On

RewriteBase /test/

# replace spaces with underscores
RewriteCond %{REQUEST_FILENAME} .*[\ ].*
RewriteRule (.*)[\ ](.*) $1_$2 [N]

# the index.php
RewriteRule ^index.php - [L]

# language tag
RewriteRule ^([a-z]{2})$ index.php?lang=$1&url= [L,QSA]
RewriteRule ^$ en [R=301,L]

# add .xhtml
RewriteCond %{REQUEST_FILENAME}.xhtml -s [OR]
RewriteCond %{REQUEST_FILENAME}.xhtml.gz -s
RewriteRule ^(.+) $1.xhtml

# add .gz
RewriteCond %{HTTP:Accept-Encoding} .*gzip.*
RewriteCond %{REQUEST_FILENAME}.gz -s
RewriteRule ^(.+) $1.gz

# send correct mime type
#RewriteCond %{REQUEST_FILENAME} -s
RewriteRule \.xhtml\.gz$  - [L,T=application/xhtml+xml]
rewriteLog语句太大,无法粘贴。一个请求就用13MB的数据填充文件。以下是摘要:

(IP) - - [date] [host] (3) [perdir /htdocs/test/] add path info postfix: /htdocs/test/de -> /htdocs/test/de/This is a test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] strip per-dir prefix: /htdocs/test/de/This is a test -> de/This is a test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] applying pattern '(.*)[\ ](.*)' to uri 'de/This is a test'
(IP) - - [date] [host] (2) [perdir /htdocs/test/] rewrite 'de/This is a test' -> 'de/This is a_test'
(IP) - - [date] [host] (3) [perdir /htdocs/test/] add per-dir prefix: de/This is a_test -> /htdocs/test/de/This is a_test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] add path info postfix: /htdocs/test/de/This is a_test -> /htdocs/test/de/This is a_test/This is a test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] strip per-dir prefix: /htdocs/test/de/This is a_test/This is a test -> de/This is a_test/This is a test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] applying pattern '(.*)[\ ](.*)' to uri 'de/This is a_test/This is a test'
(IP) - - [date] [host] (2) [perdir /htdocs/test/] rewrite 'de/This is a_test/This is a test' -> 'de/This is a_test/This is a_test'
(IP) - - [date] [host] (3) [perdir /htdocs/test/] add per-dir prefix: de/This is a_test/This is a_test -> /htdocs/test/de/This is a_test/This is a_test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] add path info postfix: /htdocs/test/de/This is a_test/This is a_test -> /htdocs/test/de/This is a_test/This is a_test/This is a test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] strip per-dir prefix: /htdocs/test/de/This is a_test/This is a_test/This is a test -> de/This is a_test/This is a_test/This is a test
(IP) - - [date] [host] (3) [perdir /htdocs/test/] applying pattern '(.*)[\ ](.*)' to uri 'de/This is a_test/This is a_test/This is a test'
(IP) - - [date] [host] (2) [perdir /htdocs/test/] rewrite 'de/This is a_test/This is a_test/This is a test' -> 'de/This is a_test/This is a_test/This is a_test'
(IP) - - [date] [host] (3) [perdir /htdocs/test/] add per-dir prefix: de/This is a_test/This is a_test/This is a_test -> /htdocs/test/de/This is a_test/This is a_test/This is a_test
... and so on ad infinitum

坏家伙是第6行:“添加路径信息后缀”。

尝试绝对替换:

RewriteRule ^([^\ ]*)\ (.*) /$1_$2 [N]

更新

看到你的更新3(很有帮助,谢谢),我又想到了两个主意:

  • 有一个apache问题:,看起来与您的类似。这是随着新技术的引入而产生的。尝试将此标志添加到您的
    重写规则中

    RewriteRule (.*)[\ ](.*) $1_$2 [N,DPI]
    
    看看这能否解决问题。需要Apache2.2.12

  • 您是否碰巧在上启用了
    ?尝试禁用它

  • 更新结束

    您的设置:

    RewriteEngine on
    RewriteCond %{REQUEST_FILENAME} .*[\ ].*
    RewriteRule (.*)[\ ](.*) $1_$2 [N]
    
    适合我(
    http://localhost/test/This 是一个示例.html
    ,重写
    VirtualHost
    config中的规则,apache 2.2.14)。这是我的
    RewriteLog
    (带有
    rewriteloglevel2
    ):

    D:/var/www/test/This\u是一个示例。html
    不存在时,我得到一个
    404
    -但没有segfault


    你能发布你的
    重写日志吗?你把重写规则放在哪里?进入
    .htaccess
    ?您是否有任何指令(
    AliasMatch
    等)也适用于您的url?

    总体而言,如果提供可重复的测试用例,Apache开发人员将非常认真地对待httpd中的SIGSEGV。如果附加调试器并捕获回溯跟踪,则情况更糟。

    不,这不起作用,结果相同。我现在用一个条件来绕过它:
    RewriteCond%{REQUEST\u FILENAME}.*[\].
    当我添加RewriteCond时,它也适用于我。但问题是,为什么我需要重写?如果你看一下我在问题中的重写规则,它应该一圈一圈地循环,直到没有剩余的空间,而不需要重写。我的问题是,它为什么不这样做。它在这里也可以工作,而不使用
    RewriteCond
    (相同的
    RewriteLog
    )。那么:您的
    重写日志
    看起来像什么,您的重写规则在
    .htaccess
    中,和/或是否有其他指令与所讨论的url匹配?重写规则在.htaccess文件中。请注意我在问题中的第一次更新,SEGFULT仅在规则之前存在类似文件夹的组件时发生。我将把上面的重写日志粘贴到问题中。哇,谢谢你找出了这个bug。看起来真的是我的问题。不幸的是,我还有2.2.11,但我会在赏金到期之前尝试设置2.2.12来验证这一点。现在我要把这个问题打印出来,框起来,贴在墙上。最后,有多少mod_重写问题以“这不是你的错,这是mod_重写中的错误”?;-)如何定义您的
    /virtual directory
    (或者它是
    /test
    )以及您的[ErrorDocument][1]在
    /virtual directory
    中的作用是什么?[1] :我相应地更新了问题。ErrorDocument仅为404定义,它是指向与.htaccess文件位于同一目录中的index.php的重定向。“/virtual directory”在现实生活中是我用来区分请求语言的语言前缀(如“/en/”或“/de/”)。segfault可能会被LimitInternalRecursion(Apache 2.0.47+)或RewriteOptions MaxRedirects(2.0.45-46)禁用
    init rewrite engine with requested uri /test/This is an example.html
    rewrite '/test/This is an example.html' -> '/test/This is an_example.html'
    rewrite '/test/This is an_example.html' -> '/test/This is_an_example.html'
    rewrite '/test/This is_an_example.html' -> '/test/This_is_an_example.html'
    local path result: /test/This_is_an_example.html
    prefixed with document_root to D:/var/www/test/This_is_an_example.html
    go-ahead with D:/var/www/test/This_is_an_example.html [OK]