Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #2101 from peterbe/bug-1012672-make-sure-symbol-up…

…loads-do-not-allow-qcom-private-files

fixes bug 1012672 - Make sure symbol uploads do not allow qcom-private files
  • Loading branch information...
commit c7d7346b16e2d07fad48ea22833d01876abbbc69 2 parents 7c61689 + 235d29a
Adrian Gaudebert AdrianGaudebert authored
7 webapp-django/crashstats/settings/base.py
View
@@ -304,3 +304,10 @@
# Default for how many users to display in the Users Admin UI
USERS_ADMIN_BATCH_SIZE = 10
+
+# Individual strings that can't be allowed in any of the lines in the
+# content of a symbols archive file.
+DISALLOWED_SYMBOLS_SNIPPETS = (
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=1012672
+ 'qcom/proprietary',
+)
72 webapp-django/crashstats/symbols/tests/test_views.py
View
@@ -11,7 +11,7 @@
from crashstats.tokens.models import Token
from crashstats.crashstats.tests.test_views import BaseTestViews
from crashstats.symbols import models
-
+from crashstats.symbols.views import check_symbols_archive_content
from .base import ZIP_FILE, TARGZ_FILE, TGZ_FILE, TAR_FILE
@@ -43,6 +43,34 @@ def _login(self):
assert self.client.login(username='test', password='secret')
return user
+ def test_check_symbols_archive_content(self):
+ content = """
+ HEADER 1
+ HEADER 2
+ Line 1
+ Line Two
+ Line Three
+ """
+
+ # check that the header is not checked
+ disallowed = ('HEADER',)
+ with self.settings(DISALLOWED_SYMBOLS_SNIPPETS=disallowed):
+ error = check_symbols_archive_content(content.strip())
+ ok_(not error)
+
+ # match something
+ disallowed = ('Two', '2')
+ with self.settings(DISALLOWED_SYMBOLS_SNIPPETS=disallowed):
+ error = check_symbols_archive_content(content.strip())
+ ok_(error)
+ ok_('Two' in error)
+
+ # match nothing
+ disallowed = ('evil', 'Bad')
+ with self.settings(DISALLOWED_SYMBOLS_SNIPPETS=disallowed):
+ error = check_symbols_archive_content(content.strip())
+ ok_(not error)
+
def test_home(self):
self._create_group_with_permission('upload_symbols')
url = reverse('symbols:home')
@@ -147,6 +175,23 @@ def test_web_upload(self):
ok_(symbol_upload.file_exists)
ok_(symbol_upload.content)
+ def test_web_upload_disallowed_content(self):
+ url = reverse('symbols:web_upload')
+ user = self._login()
+ self._add_permission(user, 'upload_symbols')
+ # because the file ZIP_FILE contains the word `south-africa-flag.jpeg`
+ # it should not be allowed to be uploaded
+ disallowed = ('flag',)
+ with self.settings(MEDIA_ROOT=self.tmp_dir,
+ DISALLOWED_SYMBOLS_SNIPPETS=disallowed):
+ with open(ZIP_FILE) as file_object:
+ response = self.client.post(
+ url,
+ {'file': file_object}
+ )
+ eq_(response.status_code, 400)
+ ok_('flag' in response.content)
+
def test_web_upload_tar_gz_file(self):
url = reverse('symbols:web_upload')
user = self._login()
@@ -271,6 +316,31 @@ def test_upload(self):
ok_(symbol_upload.file_exists)
ok_(symbol_upload.content)
+ def test_upload_disallowed_content(self):
+ user = User.objects.create(username='user')
+ self._add_permission(user, 'upload_symbols')
+ token = Token.objects.create(
+ user=user,
+ )
+ token.permissions.add(
+ Permission.objects.get(codename='upload_symbols')
+ )
+
+ url = reverse('symbols:upload')
+ # because the file ZIP_FILE contains the word `south-africa-flag.jpeg`
+ # it should not be allowed to be uploaded
+ disallowed = ('flag',)
+ with self.settings(MEDIA_ROOT=self.tmp_dir,
+ DISALLOWED_SYMBOLS_SNIPPETS=disallowed):
+ with open(ZIP_FILE, 'rb') as file_object:
+ response = self.client.post(
+ url,
+ {'file.zip': file_object},
+ HTTP_AUTH_TOKEN=token.key
+ )
+ eq_(response.status_code, 400)
+ ok_('flag' in response.content)
+
def test_upload_empty_file(self):
user = User.objects.create(username='user')
self._add_permission(user, 'upload_symbols')
31 webapp-django/crashstats/symbols/views.py
View
@@ -18,6 +18,20 @@
from . import utils
+def check_symbols_archive_content(content, header_length=2):
+ """return an error if there was something wrong"""
+ for i, line in enumerate(content.splitlines()):
+ # the first two lines of the `content` is just headers
+ if i <= (header_length - 1):
+ continue
+ for snippet in settings.DISALLOWED_SYMBOLS_SNIPPETS:
+ if snippet in line:
+ return (
+ "Content of archive file contains the snippet "
+ "'%s' which is not allowed\n" % snippet
+ )
+
+
@login_required
def home(request):
context = {}
@@ -54,12 +68,18 @@ def web_upload(request):
content_type = 'application/x-gzip'
else:
content_type = form.cleaned_data['file'].content_type
+ content = utils.preview_archive_content(
+ form.cleaned_data['file'].file,
+ content_type
+ )
+
+ error = check_symbols_archive_content(content)
+ if error:
+ return http.HttpResponseBadRequest(error)
+
symbols_upload = models.SymbolsUpload.objects.create(
user=request.user,
- content=utils.preview_archive_content(
- form.cleaned_data['file'].file,
- content_type
- ),
+ content=content,
size=form.cleaned_data['file'].size,
filename=os.path.basename(form.cleaned_data['file'].name),
file=form.cleaned_data['file'],
@@ -122,6 +142,9 @@ def upload(request):
upload,
utils.filename_to_mimetype(name)
)
+ error = check_symbols_archive_content(content)
+ if error:
+ return http.HttpResponseBadRequest(error)
models.SymbolsUpload.objects.create(
user=request.user,
Please sign in to comment.
Something went wrong with that request. Please try again.