Merge "Add a script to parse an block-based ota package"
diff --git a/core/Makefile b/core/Makefile
index 7a8ba1f..e20a5a2 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -191,11 +191,16 @@
BUILDINFO_SH := build/tools/buildinfo.sh
-# TARGET_BUILD_FLAVOR and ro.build.flavor are used only by the test harness to distinguish builds.
+# TARGET_BUILD_FLAVOR and ro.build.flavor are used only by the test
+# harness to distinguish builds. Only add _asan for a sanitized build
+# if it isn't already a part of the flavor (via a dedicated lunch
+# config for example).
TARGET_BUILD_FLAVOR := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)
ifdef SANITIZE_TARGET
+ifeq (,$(findstring _asan,$(TARGET_BUILD_FLAVOR)))
TARGET_BUILD_FLAVOR := $(TARGET_BUILD_FLAVOR)_asan
endif
+endif
ifdef TARGET_SYSTEM_PROP
system_prop_file := $(TARGET_SYSTEM_PROP)
diff --git a/core/binary.mk b/core/binary.mk
index 8a238ba..b2b8186 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -1684,6 +1684,12 @@
ifeq ($(my_tidy_flags),)
my_tidy_flags := $(call default_tidy_header_filter,$(LOCAL_PATH))
endif
+
+ # We might be using the static analyzer through clang-tidy.
+ # https://bugs.llvm.org/show_bug.cgi?id=32914
+ ifneq ($(my_tidy_checks),)
+ my_tidy_flags += "-extra-arg-before=-D__clang_analyzer__"
+ endif
endif
endif
diff --git a/core/definitions.mk b/core/definitions.mk
index 10d26c4..64bdfe6 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -3238,6 +3238,141 @@
endef
###########################################################
+## Path Cleaning
+###########################################################
+
+# Remove "dir .." combinations (but keep ".. ..")
+#
+# $(1): The expanded path, where / is converted to ' ' to work with $(word)
+define _clean-path-strip-dotdot
+$(strip \
+ $(if $(word 2,$(1)),
+ $(if $(call streq,$(word 2,$(1)),..),
+ $(if $(call streq,$(word 1,$(1)),..),
+ $(word 1,$(1)) $(call _clean-path-strip-dotdot,$(wordlist 2,$(words $(1)),$(1)))
+ ,
+ $(call _clean-path-strip-dotdot,$(wordlist 3,$(words $(1)),$(1)))
+ )
+ ,
+ $(word 1,$(1)) $(call _clean-path-strip-dotdot,$(wordlist 2,$(words $(1)),$(1)))
+ )
+ ,
+ $(1)
+ )
+)
+endef
+
+# Remove any leading .. from the path (in case of /..)
+#
+# Should only be called if the original path started with /
+# $(1): The expanded path, where / is converted to ' ' to work with $(word)
+define _clean-path-strip-root-dotdots
+$(strip $(if $(call streq,$(firstword $(1)),..),
+ $(call _clean-path-strip-root-dotdots,$(wordlist 2,$(words $(1)),$(1))),
+ $(1)))
+endef
+
+# Call _clean-path-strip-dotdot until the path stops changing
+# $(1): Non-empty if this path started with a /
+# $(2): The expanded path, where / is converted to ' ' to work with $(word)
+define _clean-path-expanded
+$(strip \
+ $(eval _ep := $(call _clean-path-strip-dotdot,$(2)))
+ $(if $(1),$(eval _ep := $(call _clean-path-strip-root-dotdots,$(_ep))))
+ $(if $(call streq,$(2),$(_ep)),
+ $(_ep),
+ $(call _clean-path-expanded,$(1),$(_ep))))
+endef
+
+# Clean the file path -- remove //, dir/.., extra .
+#
+# This should be the same semantics as golang's filepath.Clean
+#
+# $(1): The file path to clean
+define clean-path
+$(strip \
+ $(if $(call streq,$(words $(1)),1),
+ $(eval _rooted := $(filter /%,$(1)))
+ $(eval _expanded_path := $(filter-out .,$(subst /,$(space),$(1))))
+ $(eval _path := $(if $(_rooted),/)$(subst $(space),/,$(call _clean-path-expanded,$(_rooted),$(_expanded_path))))
+ $(if $(_path),
+ $(_path),
+ .
+ )
+ ,
+ $(if $(call streq,$(words $(1)),0),
+ .,
+ $(error Call clean-path with only one path (without spaces))
+ )
+ )
+)
+endef
+
+ifeq ($(TEST_MAKE_clean_path),true)
+ define my_test
+ $(if $(call streq,$(call clean-path,$(1)),$(2)),,
+ $(eval my_failed := true)
+ $(warning clean-path test '$(1)': expected '$(2)', got '$(call clean-path,$(1))'))
+ endef
+ my_failed :=
+
+ # Already clean
+ $(call my_test,abc,abc)
+ $(call my_test,abc/def,abc/def)
+ $(call my_test,a/b/c,a/b/c)
+ $(call my_test,.,.)
+ $(call my_test,..,..)
+ $(call my_test,../..,../..)
+ $(call my_test,../../abc,../../abc)
+ $(call my_test,/abc,/abc)
+ $(call my_test,/,/)
+
+ # Empty is current dir
+ $(call my_test,,.)
+
+ # Remove trailing slash
+ $(call my_test,abc/,abc)
+ $(call my_test,abc/def/,abc/def)
+ $(call my_test,a/b/c/,a/b/c)
+ $(call my_test,./,.)
+ $(call my_test,../,..)
+ $(call my_test,../../,../..)
+ $(call my_test,/abc/,/abc)
+
+ # Remove doubled slash
+ $(call my_test,abc//def//ghi,abc/def/ghi)
+ $(call my_test,//abc,/abc)
+ $(call my_test,///abc,/abc)
+ $(call my_test,//abc//,/abc)
+ $(call my_test,abc//,abc)
+
+ # Remove . elements
+ $(call my_test,abc/./def,abc/def)
+ $(call my_test,/./abc/def,/abc/def)
+ $(call my_test,abc/.,abc)
+
+ # Remove .. elements
+ $(call my_test,abc/def/ghi/../jkl,abc/def/jkl)
+ $(call my_test,abc/def/../ghi/../jkl,abc/jkl)
+ $(call my_test,abc/def/..,abc)
+ $(call my_test,abc/def/../..,.)
+ $(call my_test,/abc/def/../..,/)
+ $(call my_test,abc/def/../../..,..)
+ $(call my_test,/abc/def/../../..,/)
+ $(call my_test,abc/def/../../../ghi/jkl/../../../mno,../../mno)
+ $(call my_test,/../abc,/abc)
+
+ # Combinations
+ $(call my_test,abc/./../def,def)
+ $(call my_test,abc//./../def,def)
+ $(call my_test,abc/../../././../def,../../def)
+
+ ifdef my_failed
+ $(error failed clean-path test)
+ endif
+endif
+
+###########################################################
## Other includes
###########################################################
diff --git a/core/package_internal.mk b/core/package_internal.mk
index f9f8e35..6b07be6 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -92,6 +92,7 @@
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
else
need_compile_res := true
+ LOCAL_RESOURCE_DIR := $(foreach d,$(LOCAL_RESOURCE_DIR),$(call clean-path,$(d)))
endif
package_resource_overlays := $(strip \
diff --git a/core/static_java_library.mk b/core/static_java_library.mk
index a8b0103..343b949 100644
--- a/core/static_java_library.mk
+++ b/core/static_java_library.mk
@@ -39,6 +39,7 @@
# A static Java library needs to explicily set LOCAL_RESOURCE_DIR.
ifdef LOCAL_RESOURCE_DIR
need_compile_res := true
+LOCAL_RESOURCE_DIR := $(foreach d,$(LOCAL_RESOURCE_DIR),$(call clean-path,$(d)))
endif
ifdef LOCAL_USE_AAPT2
ifneq ($(LOCAL_STATIC_ANDROID_LIBRARIES),)
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 1a7e10e..2090400 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -181,14 +181,14 @@
OPTIONS.payload_signer = None
OPTIONS.payload_signer_args = []
OPTIONS.extracted_input = None
+OPTIONS.key_passwords = []
METADATA_NAME = 'META-INF/com/android/metadata'
UNZIP_PATTERN = ['IMAGES/*', 'META/*']
def SignOutput(temp_zip_name, output_zip_name):
- key_passwords = common.GetKeyPasswords([OPTIONS.package_key])
- pw = key_passwords[OPTIONS.package_key]
+ pw = OPTIONS.key_passwords[OPTIONS.package_key]
common.SignFile(temp_zip_name, output_zip_name, OPTIONS.package_key, pw,
whole_file=True)
@@ -1021,21 +1021,17 @@
# The place where the output from the subprocess should go.
log_file = sys.stdout if OPTIONS.verbose else subprocess.PIPE
- # Setup signing keys.
- if OPTIONS.package_key is None:
- OPTIONS.package_key = OPTIONS.info_dict.get(
- "default_system_dev_certificate",
- "build/target/product/security/testkey")
-
# A/B updater expects a signing key in RSA format. Gets the key ready for
# later use in step 3, unless a payload_signer has been specified.
if OPTIONS.payload_signer is None:
cmd = ["openssl", "pkcs8",
"-in", OPTIONS.package_key + OPTIONS.private_key_suffix,
- "-inform", "DER", "-nocrypt"]
+ "-inform", "DER"]
+ pw = OPTIONS.key_passwords[OPTIONS.package_key]
+ cmd.extend(["-passin", "pass:" + pw] if pw else ["-nocrypt"])
rsa_key = common.MakeTempFile(prefix="key-", suffix=".key")
cmd.extend(["-out", rsa_key])
- p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
+ p1 = common.Run(cmd, verbose=False, stdout=log_file, stderr=subprocess.STDOUT)
p1.communicate()
assert p1.returncode == 0, "openssl pkcs8 failed"
@@ -1383,6 +1379,17 @@
ab_update = OPTIONS.info_dict.get("ab_update") == "true"
+ # Use the default key to sign the package if not specified with package_key.
+ # package_keys are needed on ab_updates, so always define them if an
+ # ab_update is getting created.
+ if not OPTIONS.no_signing or ab_update:
+ if OPTIONS.package_key is None:
+ OPTIONS.package_key = OPTIONS.info_dict.get(
+ "default_system_dev_certificate",
+ "build/target/product/security/testkey")
+ # Get signing keys
+ OPTIONS.key_passwords = common.GetKeyPasswords([OPTIONS.package_key])
+
if ab_update:
if OPTIONS.incremental_source is not None:
OPTIONS.target_info_dict = OPTIONS.info_dict
@@ -1448,13 +1455,6 @@
raise common.ExternalError(
"--- target build has specified no recovery ---")
- # Use the default key to sign the package if not specified with package_key.
- if not OPTIONS.no_signing:
- if OPTIONS.package_key is None:
- OPTIONS.package_key = OPTIONS.info_dict.get(
- "default_system_dev_certificate",
- "build/target/product/security/testkey")
-
# Set up the output zip. Create a temporary zip file if signing is needed.
if OPTIONS.no_signing:
if os.path.exists(args[1]):