aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES19
-rw-r--r--mako/__init__.py2
-rw-r--r--mako/lookup.py2
-rw-r--r--mako/template.py18
-rw-r--r--test/templates/othersubdir/foo.html0
-rw-r--r--test/test_lookup.py32
-rw-r--r--test/test_template.py23
7 files changed, 83 insertions, 13 deletions
diff --git a/CHANGES b/CHANGES
index a6bae66..01ec4dc 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,22 @@
+0.5
+- A Template is explicitly disallowed
+ from having a url that normalizes to relative outside
+ of the root. That is, if the Lookup is based
+ at /home/mytemplates, an include that would place
+ the ultimate template at
+ /home/mytemplates/../some_other_directory,
+ i.e. outside of /home/mytemplates,
+ is disallowed. This usage was never intended
+ despite the lack of an explicit check.
+ The main issue this causes
+ is that module files can be written outside
+ of the module root (or raise an error, if file perms aren't
+ set up), and can also lead to the same template being
+ cached in the lookup under multiple, relative roots.
+ TemplateLookup instead has always supported multiple
+ file roots for this purpose.
+ [ticket:174]
+
0.4.2
- Fixed bug regarding <%call>/def calls w/ content
whereby the identity of the "caller" callable
diff --git a/mako/__init__.py b/mako/__init__.py
index c9913eb..5b067a3 100644
--- a/mako/__init__.py
+++ b/mako/__init__.py
@@ -5,5 +5,5 @@
# the MIT License: http://www.opensource.org/licenses/mit-license.php
-__version__ = '0.4.2'
+__version__ = '0.5.0'
diff --git a/mako/lookup.py b/mako/lookup.py
index b397d21..e3d92da 100644
--- a/mako/lookup.py
+++ b/mako/lookup.py
@@ -204,7 +204,7 @@ class TemplateLookup(TemplateCollection):
Note the "relativeto" argument is not supported here at the moment.
"""
-
+
try:
if self.filesystem_checks:
return self._check(uri, self._collection[uri])
diff --git a/mako/template.py b/mako/template.py
index 903dc42..3d02c55 100644
--- a/mako/template.py
+++ b/mako/template.py
@@ -163,7 +163,17 @@ class Template(object):
else:
self.module_id = "memory:" + hex(id(self))
self.uri = self.module_id
-
+
+ u_norm = self.uri
+ if u_norm.startswith("/"):
+ u_norm = u_norm[1:]
+ u_norm = os.path.normpath(u_norm)
+ if u_norm.startswith(".."):
+ raise exceptions.TemplateLookupException(
+ "Template uri \"%s\" is invalid - "
+ "it cannot be relative outside "
+ "of the root path." % self.uri)
+
self.input_encoding = input_encoding
self.output_encoding = output_encoding
self.encoding_errors = encoding_errors
@@ -203,18 +213,14 @@ class Template(object):
if module_filename is not None:
path = module_filename
elif module_directory is not None:
- u = self.uri
- if u[0] == '/':
- u = u[1:]
path = os.path.abspath(
os.path.join(
os.path.normpath(module_directory),
- os.path.normpath(u) + ".py"
+ u_norm + ".py"
)
)
else:
path = None
-
module = self._compile_from_file(path, filename)
else:
raise exceptions.RuntimeException(
diff --git a/test/templates/othersubdir/foo.html b/test/templates/othersubdir/foo.html
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/templates/othersubdir/foo.html
diff --git a/test/test_lookup.py b/test/test_lookup.py
index 190d8a5..40b9009 100644
--- a/test/test_lookup.py
+++ b/test/test_lookup.py
@@ -1,9 +1,11 @@
from mako.template import Template
-from mako import lookup, exceptions
+from mako import lookup, exceptions, runtime
+from mako.util import FastEncodingBuffer
from util import flatten_result, result_lines
import unittest
+import os
-from test import TemplateTest, template_base, module_base
+from test import TemplateTest, template_base, module_base, assert_raises_message
tl = lookup.TemplateLookup(directories=[template_base])
class LookupTest(unittest.TestCase):
@@ -74,3 +76,29 @@ class LookupTest(unittest.TestCase):
)
assert f.uri not in tl._collection
+ def test_dont_accept_relative_outside_of_root(self):
+ """test the mechanics of an include where
+ the include goes outside of the path"""
+ tl = lookup.TemplateLookup(directories=[os.path.join(template_base, "subdir")])
+ index = tl.get_template("index.html")
+
+ ctx = runtime.Context(FastEncodingBuffer())
+ ctx._with_template=index
+
+ assert_raises_message(
+ exceptions.TemplateLookupException,
+ "Template uri \"../index.html\" is invalid - it "
+ "cannot be relative outside of the root path",
+ runtime._lookup_template, ctx, "../index.html", index.uri
+ )
+
+ assert_raises_message(
+ exceptions.TemplateLookupException,
+ "Template uri \"../othersubdir/foo.html\" is invalid - it "
+ "cannot be relative outside of the root path",
+ runtime._lookup_template, ctx, "../othersubdir/foo.html", index.uri
+ )
+
+ # this is OK since the .. cancels out
+ t = runtime._lookup_template(ctx, "foo/../index.html", index.uri)
+
diff --git a/test/test_template.py b/test/test_template.py
index a62783e..4d301aa 100644
--- a/test/test_template.py
+++ b/test/test_template.py
@@ -9,7 +9,7 @@ import os
from util import flatten_result, result_lines
import codecs
from test import TemplateTest, eq_, template_base, module_base, \
- skip_if, assert_raises
+ skip_if, assert_raises, assert_raises_message
class EncodingTest(TemplateTest):
def test_unicode(self):
@@ -918,8 +918,25 @@ class FilenameToURITest(TemplateTest):
finally:
os.path = current_path
-
-
+ def test_dont_accept_relative_outside_of_root(self):
+ assert_raises_message(
+ exceptions.TemplateLookupException,
+ "Template uri \"../../foo.html\" is invalid - it "
+ "cannot be relative outside of the root path",
+ Template, "test", uri="../../foo.html",
+ )
+
+ assert_raises_message(
+ exceptions.TemplateLookupException,
+ "Template uri \"/../../foo.html\" is invalid - it "
+ "cannot be relative outside of the root path",
+ Template, "test", uri="/../../foo.html",
+ )
+
+ # normalizes in the root is OK
+ t = Template("test", uri="foo/bar/../../foo.html")
+ eq_(t.uri, "foo/bar/../../foo.html")
+
class ModuleTemplateTest(TemplateTest):
def test_module_roundtrip(self):
lookup = TemplateLookup()