diff options
author | Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de> | 2012-03-28 16:58:20 +0200 |
---|---|---|
committer | Jan Lehnardt <jan@apache.org> | 2012-05-01 14:03:45 +0100 |
commit | 30334ac87a90fc88804037cab073caf9fc48de38 (patch) | |
tree | 586763ab202accf5b19da0cdee979cc4eddddb27 | |
parent | 56744f2f4b63c396a68e892fcfaec1a84ab95bf2 (diff) | |
download | couchdb-30334ac87a90fc88804037cab073caf9fc48de38.tar.gz |
Limit rewrite recursion depth
Loops in the rewriter would end up pegging the CPU until memory was
exhausted. Max recursion is now configurable and limited to 100
iterations.
Fixes: COUCHDB-1441
-rw-r--r-- | CHANGES | 2 | ||||
-rw-r--r-- | share/www/script/test/rewrite.js | 16 | ||||
-rw-r--r-- | src/couchdb/couch_httpd_rewrite.erl | 11 |
3 files changed, 29 insertions, 0 deletions
@@ -10,6 +10,8 @@ HTTP Interface: * No longer rewrites the X-CouchDB-Requested-Path during recursive calls to the rewriter. + * Limit recursion depth in the URL rewriter. Defaults to a maximum + of 100 invocations but is configurable. Version 1.2.0 ------------- diff --git a/share/www/script/test/rewrite.js b/share/www/script/test/rewrite.js index aaf8b69e9..352e6b99b 100644 --- a/share/www/script/test/rewrite.js +++ b/share/www/script/test/rewrite.js @@ -457,4 +457,20 @@ couchTests.rewrite = function(debug) { var url = "/test_suite_db/_design/requested_path/_rewrite/show_rewritten"; var res = CouchDB.request("GET", url); TEquals(url, res.responseText, "returned the original url"); + + var ddoc_loop = { + _id: "_design/loop", + rewrites: [{ "from": "loop", "to": "_rewrite/loop"}] + }; + db.save(ddoc_loop); + + run_on_modified_server( + [{section: "httpd", + key: "rewrite_limit", + value: "2"}], + function(){ + var url = "/test_suite_db/_design/loop/_rewrite/loop"; + var xhr = CouchDB.request("GET", url); + T(xhr.status = 400); + }); } diff --git a/src/couchdb/couch_httpd_rewrite.erl b/src/couchdb/couch_httpd_rewrite.erl index cb164cd1f..207891ab9 100644 --- a/src/couchdb/couch_httpd_rewrite.erl +++ b/src/couchdb/couch_httpd_rewrite.erl @@ -119,6 +119,17 @@ handle_rewrite_req(#httpd{ Prefix = <<"/", DbName/binary, "/", DesignId/binary>>, QueryList = lists:map(fun decode_query_value/1, couch_httpd:qs(Req)), + MaxRewritesList = couch_config:get("httpd", "rewrite_limit", "100"), + MaxRewrites = list_to_integer(MaxRewritesList), + NRewrites = case get(couch_rewrite_count) of + undefined -> + put(couch_rewrite_count, 1); + NumRewrites when NumRewrites < MaxRewrites -> + put(couch_rewrite_count, NumRewrites + 1); + _ -> + throw({bad_request, <<"Exceeded rewrite recursion limit">>}) + end, + #doc{body={Props}} = DDoc, % get rules from ddoc |