1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
media / ffmpeg / scripts / check_merge.py [blame]
#!/usr/bin/env python3
#
# Copyright 2018 The Chromium Authors.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Verify HEAD against upstream to see if anything bad has been added to
# HEAD that we would not want to roll. For example, if HEAD introduces any
# UNCHECKED_BITSTREAM_READERs, then we definitely want to fix that before
# including HEAD in Chromium.
#
# Usage: check_merge.py [new_branch]
# where |new_branch| is the branch that we'd like to compare to upstream.
import os
import re
import sys
import subprocess
# The current good ffmpeg + config that we're diffing against.
EXISTING_COMMIT = "origin/master" # nocheck
# If any of these regexes match, it indicates failure. Generally, we want to
# catch any change in how these are defined. These are checked against things
# that are added with respect to |EXISTING_COMMIT| by the commit we're checking.
#
# Remember that we're going to check ffmpeg files and Chromium files (e.g.,
# the build configs for each platform, ffmpeg_generated.gni, etc.).
# TODO(liberato): consider making these a dictionary, with the value as some
# descriptive text (e.g., the bug number) about why it's not allowed.
INSERTION_TRIPWIRES = [
# In Chromium, all codecs should use the safe bitstream reader. Roller must
# undo any new usage of the unchecked reader.
"^.define.*UNCHECKED_BITSTREAM_READER.*1",
# In Chromium, explicitly skipping some matroskadec code blocks for
# the following CONFIG variables (which should remain defined as 0) is
# necessary to remove code that may be a security risk. Discuss with cevans@
# before removing these explicit skips or enabling these variables.
"^.define.*CONFIG_LZO.*1",
"^.define.*CONFIG_SIPR_DECODER.*1",
"^.define.*CONFIG_RA_288_DECODER.*1",
"^.define.*CONFIG_COOK_DECODER.*1",
"^.define.*CONFIG_ATRAC3_DECODER.*1",
# Miscellaneous tripwires.
"^.define.*CONFIG_SPDIF_DEMUXER.*1",
"^.define.*CONFIG_W64_DEMUXER.*1",
"^.define.*[Vv]4[Ll]2.*1",
"^.define.*CONFIG_PRORES_.*1",
]
# Filenames that will be excluded from the regex matching.
# Note: chromium/scripts can be removed once the scripts move out of ffmpeg.
EXCLUDED_FILENAMES = [
r"^configure$",
r"^chromium/scripts/",
r"^chromium/patches/",
]
def search_regexps(text, regexps):
return [r for r in regexps if re.search(r, text)]
def main(argv):
# What we're considering merging, and would like to check. Normally, this
# is HEAD, but you might want to verify some previous merge.
if len(argv) > 1:
new_commit = argv[1]
else:
new_commit = "HEAD"
print(f"Comparing {new_commit} to baseline {EXISTING_COMMIT}...")
diff = subprocess.Popen(
["git", "diff", "-U0", EXISTING_COMMIT, new_commit],
stdout=subprocess.PIPE).communicate()[0].decode(sys.stdout.encoding)
filename = None
skip = False
files_encountered = 0
files_skipped = 0
failures = set()
for line in diff.splitlines():
if line.startswith("+++"):
# +++ b/filename => filename
filename = line.split("/", 1)[1]
skip = False
files_encountered += 1
if search_regexps(filename, EXCLUDED_FILENAMES):
skip = True
files_skipped += 1
elif line.startswith("+") and not skip:
# |line| is an insertion into |new_commit|.
# Drop the leading "+" from the string being searched.
tripwire = search_regexps(line[1:], INSERTION_TRIPWIRES)
if tripwire:
failures.add("Tripwire '%s' found in %s" %
(tripwire, filename))
# If we have failures, then print them and fail.
if failures:
for failure in failures:
print(f"Failure: {failure}")
sys.exit(2)
checked = files_encountered - files_skipped
print(f"No problems found! Checked {checked}, skipped {files_skipped}.")
if __name__ == '__main__':
main(sys.argv)