diff --git a/test/test_cve.py b/test/test_cve.py index cf699a33..cae6b4dd 100644 --- a/test/test_cve.py +++ b/test/test_cve.py @@ -64,6 +64,30 @@ def set_and_assert_cve_data(db, client, cve_id, route): def test_add_cve(db, client): set_and_assert_cve_data(db, client, 'CVE-1122-0042', url_for('tracker.add_cve')) +@logged_in +def test_add_cve_normalizes_wrapped_description(db, client): + description = ( + 'This vulnerability description contains enough characters to exceed the seventy-character wrapping threshold\n' + 'and the continuation should be joined to the preceding line.\n\n' + 'Second paragraph stays separate.' + ) + + expected = ( + 'This vulnerability description contains enough characters to exceed the seventy-character wrapping threshold ' + 'and the continuation should be joined to the preceding line.\n\n' + 'Second paragraph stays separate.' + ) + + response = client.post( + url_for('tracker.add_cve'), + follow_redirects=True, + data=default_issue_dict(dict(description=description)), + ) + + assert response.status_code == 200 + + cve = CVE.query.get(DEFAULT_ISSUE_ID) + assert cve.description == expected @logged_in(role=UserRole.reporter) def test_reporter_can_add(db, client): diff --git a/tracker/view/add.py b/tracker/view/add.py index fb3693b1..8ff15143 100644 --- a/tracker/view/add.py +++ b/tracker/view/add.py @@ -1,3 +1,5 @@ +import re + from flask import flash from flask import redirect from flask import render_template @@ -30,6 +32,37 @@ ERROR_ISSUE_REFERENCED_BY_ADVISORY = 'Insufficient permissions to edit {} that is referenced by an already published advisory!' +def normalize_description(description): + if not description: + return description + + description = ( + description.replace('\r\n', '\n') + .replace('\r', '\n') + .strip() + ) + + paragraphs = re.split(r'\n[ \t]*\n+', description) + normalized_paragraphs = [] + + for paragraph in paragraphs: + lines = paragraph.splitlines() + if not lines: + continue + + normalized = lines[0].strip() + + for previous, line in zip(lines, lines[1:]): + if len(previous.strip()) >= 70: + normalized += ' ' + line.strip() + else: + normalized += '\n' + line.strip() + + normalized_paragraphs.append(normalized) + + return '\n\n'.join(normalized_paragraphs) + + @tracker.route('/cve/add', methods=['GET', 'POST']) @reporter_required def add_cve(): @@ -84,11 +117,12 @@ def add_cve(): form.remote.data = cve.remote.name # try to merge description - if form.description.data: + description = normalize_description(form.description.data) + if description: if not cve.description: - cve.description = form.description.data + cve.description = description merged = True - elif form.description.data != cve.description: + elif description != cve.description: not_merged.append(form.description) form.description.data = cve.description @@ -136,7 +170,7 @@ def add_cve(): cve = CVE() cve.id = form.cve.data cve.issue_type = form.issue_type.data - cve.description = form.description.data + cve.description = normalize_description(form.description.data) cve.severity = Severity.fromstring(form.severity.data) cve.remote = Remote.fromstring(form.remote.data) cve.reference = form.reference.data