зеркало из https://github.com/mozilla/treeherder.git
Bug 1369067 - file security bugs: provide option and auto-enable it based on search terms (#7201)
This commit is contained in:
Родитель
550d535480
Коммит
db200cb921
|
@ -101,6 +101,23 @@ describe('BugFiler', () => {
|
|||
);
|
||||
};
|
||||
|
||||
const getBugFilerForSecurityCheck = (suggestions) => {
|
||||
return mount(
|
||||
<BugFilerClass
|
||||
isOpen={isOpen}
|
||||
toggle={toggle}
|
||||
suggestion={suggestions[0]}
|
||||
suggestions={suggestions}
|
||||
fullLog={fullLog}
|
||||
parsedLog={parsedLog}
|
||||
reftestUrl={isReftest(selectedJob) ? reftest : ''}
|
||||
successCallback={successCallback}
|
||||
jobGroupName={selectedJob.job_group_name}
|
||||
notify={() => {}}
|
||||
/>,
|
||||
);
|
||||
};
|
||||
|
||||
test('parses a crash suggestion', () => {
|
||||
const summary =
|
||||
'PROCESS-CRASH | browser/components/search/test/browser_searchbar_smallpanel_keyboard_navigation.js | application crashed [@ js::GCMarker::eagerlyMarkChildren]';
|
||||
|
@ -255,6 +272,32 @@ describe('BugFiler', () => {
|
|||
expect(summary[1]).toBe('wide--cover--width.html');
|
||||
});
|
||||
|
||||
test('should set as security bug if summary contains initially a relevant search term', () => {
|
||||
const suggestions = [
|
||||
{
|
||||
bugs: {},
|
||||
search_terms: [],
|
||||
search:
|
||||
'SUMMARY: AddressSanitizer: heap-use-after-free /builds/worker/checkouts/gecko/mock/folder/file.c:12:34 in mock::MockComponent::MockMethod(mock::squirrel::Weasel*)',
|
||||
},
|
||||
];
|
||||
const bugFiler = getBugFilerForSecurityCheck(suggestions);
|
||||
expect(bugFiler.state().isSecurityIssue).toBe(true);
|
||||
});
|
||||
|
||||
test('should not set as security bug if summary contains initially no relevant search term', () => {
|
||||
const suggestions = [
|
||||
{
|
||||
bugs: {},
|
||||
search_terms: [],
|
||||
search:
|
||||
'TEST-UNEXPECTED-FAIL | mock/folder/test/subfolder/browser_test.js | Test timed out -',
|
||||
},
|
||||
];
|
||||
const bugFiler = getBugFilerForSecurityCheck(suggestions);
|
||||
expect(bugFiler.state().isSecurityIssue).toBe(false);
|
||||
});
|
||||
|
||||
test('should parse finding the filename when the `TEST-FOO` is not omitted', () => {
|
||||
const rawSummary =
|
||||
'TEST-UNEXPECTED-CRASH | /service-workers/service-worker/xhr.https.html | expected OK';
|
||||
|
|
|
@ -50,6 +50,7 @@ def test_create_bug(client, eleven_jobs_stored, activate_responses, test_user):
|
|||
"comment": u"Intermittent Description",
|
||||
"comment_tags": "treeherder",
|
||||
"keywords": ["intermittent-failure"],
|
||||
"groups": [],
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
|
@ -102,6 +103,7 @@ def test_create_bug_with_unicode(client, eleven_jobs_stored, activate_responses,
|
|||
"comment": u"Intermittent “description” string",
|
||||
"comment_tags": "treeherder",
|
||||
"keywords": ["intermittent-failure"],
|
||||
"groups": [],
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
|
@ -156,6 +158,7 @@ def test_create_crash_bug(client, eleven_jobs_stored, activate_responses, test_u
|
|||
"crash_signature": "[@crashsig]",
|
||||
"priority": "--",
|
||||
"keywords": ["intermittent-failure", "crash"],
|
||||
"groups": [],
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
|
@ -204,6 +207,7 @@ def test_create_unauthenticated_bug(client, eleven_jobs_stored, activate_respons
|
|||
"comment_tags": "treeherder",
|
||||
"keywords": ["intermittent-failure"],
|
||||
"see_also": "12345",
|
||||
"groups": [],
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 403
|
||||
|
@ -261,6 +265,7 @@ def test_create_bug_with_long_crash_signature(
|
|||
"crash_signature": crashsig,
|
||||
"regressed_by": "123",
|
||||
"see_also": "12345",
|
||||
"groups": [],
|
||||
},
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
|
|
@ -51,6 +51,8 @@ class BugzillaViewSet(viewsets.ViewSet):
|
|||
'description': description,
|
||||
'comment_tags': "treeherder",
|
||||
}
|
||||
if len(params.get('groups')) > 0:
|
||||
data['groups'] = params.get('groups')
|
||||
|
||||
try:
|
||||
response = make_request(url, method='POST', headers=headers, json=data)
|
||||
|
|
|
@ -167,6 +167,7 @@ export class BugFilerClass extends React.Component {
|
|||
isFilerSummaryVisible: false,
|
||||
selectedProduct: null,
|
||||
isIntermittent: true,
|
||||
isSecurityIssue: false,
|
||||
comment: '',
|
||||
searching: false,
|
||||
parsedSummary,
|
||||
|
@ -177,6 +178,10 @@ export class BugFilerClass extends React.Component {
|
|||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.checkForSecurityIssue();
|
||||
}
|
||||
|
||||
getUnhelpfulSummaryReason(summary) {
|
||||
const { suggestion } = this.props;
|
||||
const searchTerms = suggestion.search_terms;
|
||||
|
@ -384,6 +389,7 @@ export class BugFilerClass extends React.Component {
|
|||
selectedProduct,
|
||||
comment,
|
||||
isIntermittent,
|
||||
isSecurityIssue,
|
||||
checkedLogLinks,
|
||||
regressedBy,
|
||||
seeAlso,
|
||||
|
@ -487,6 +493,7 @@ export class BugFilerClass extends React.Component {
|
|||
crash_signature: crashSignature,
|
||||
severity: 'S4',
|
||||
priority,
|
||||
groups: isSecurityIssue ? ['core-security'] : [],
|
||||
comment: descriptionStrings,
|
||||
comment_tags: 'treeherder',
|
||||
};
|
||||
|
@ -536,6 +543,35 @@ export class BugFilerClass extends React.Component {
|
|||
});
|
||||
};
|
||||
|
||||
checkForSecurityIssue() {
|
||||
const { comment, isSecurityIssue, summary } = this.state;
|
||||
|
||||
if (isSecurityIssue) {
|
||||
return;
|
||||
}
|
||||
|
||||
const inputToCheck = `${summary}\n${comment}`;
|
||||
|
||||
const potentialSecurityIssues = [
|
||||
'access-violation',
|
||||
'data race',
|
||||
'double-free',
|
||||
'e5e5e5e5',
|
||||
'global-buffer-overflow',
|
||||
'heap-buffer-overflow',
|
||||
'heap-use-after-free',
|
||||
'negative-size-param',
|
||||
'stack-buffer-overflow',
|
||||
'use-after-poison',
|
||||
];
|
||||
for (const searchTerm of potentialSecurityIssues) {
|
||||
if (inputToCheck.includes(searchTerm)) {
|
||||
this.setState({ isSecurityIssue: true });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
isOpen,
|
||||
|
@ -551,6 +587,7 @@ export class BugFilerClass extends React.Component {
|
|||
thisFailure,
|
||||
isFilerSummaryVisible,
|
||||
isIntermittent,
|
||||
isSecurityIssue,
|
||||
summary,
|
||||
searching,
|
||||
checkedLogLinks,
|
||||
|
@ -666,7 +703,9 @@ export class BugFilerClass extends React.Component {
|
|||
placeholder="Intermittent..."
|
||||
pattern=".{0,255}"
|
||||
onChange={(evt) =>
|
||||
this.setState({ summary: evt.target.value })
|
||||
this.setState({ summary: evt.target.value }, () =>
|
||||
this.checkForSecurityIssue(),
|
||||
)
|
||||
}
|
||||
value={summary}
|
||||
/>
|
||||
|
@ -775,7 +814,9 @@ export class BugFilerClass extends React.Component {
|
|||
<Label for="summary-input">Comment:</Label>
|
||||
<Input
|
||||
onChange={(evt) =>
|
||||
this.setState({ comment: evt.target.value })
|
||||
this.setState({ comment: evt.target.value }, () =>
|
||||
this.checkForSecurityIssue(),
|
||||
)
|
||||
}
|
||||
type="textarea"
|
||||
id="summary-input"
|
||||
|
@ -833,6 +874,19 @@ export class BugFilerClass extends React.Component {
|
|||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-inline-flex mt-2 ml-5">
|
||||
<Label>
|
||||
<Input
|
||||
id="securityIssue"
|
||||
onChange={() =>
|
||||
this.setState({ isSecurityIssue: !isSecurityIssue })
|
||||
}
|
||||
type="checkbox"
|
||||
checked={isSecurityIssue}
|
||||
/>
|
||||
Report this as a security issue
|
||||
</Label>
|
||||
</div>
|
||||
{!!crashSignatures.length && (
|
||||
<div>
|
||||
<Label for="signature-input">Signature:</Label>
|
||||
|
|
Загрузка…
Ссылка в новой задаче