diff --git a/lib/spack/spack/relocate.py b/lib/spack/spack/relocate.py index cbee103699..2a41682147 100644 --- a/lib/spack/spack/relocate.py +++ b/lib/spack/spack/relocate.py @@ -28,6 +28,19 @@ def __init__(self, file_path, root_path): (file_path, root_path)) +class BinaryStringReplacementException(spack.error.SpackError): + """ + Raised when the size of the file changes after binary path substitution. + """ + + def __init__(self, file_path, old_len, new_len): + super(BinaryStringReplacementException, self).__init__( + "Doing a binary string replacement in %s failed.\n" + "The size of the file changed from %s to %s\n" + "when it should have remanined the same." % + (file_path, old_len, new_len)) + + def get_patchelf(): """ Builds and installs spack patchelf package on linux platforms @@ -308,8 +321,11 @@ def replace(match): f.seek(0) original_data_len = len(data) pat = re.compile(re.escape(old_dir) + b'([^\0]*?)\0') - data = pat.sub(replace, data) - assert(len(data) == original_data_len) + ndata = pat.sub(replace, data) + new_data_len = len(ndata) + if not new_data_len == original_data_len: + raise BinaryStringReplacementException( + path_name, original_data_len, new_data_len) f.write(data) f.truncate() @@ -342,8 +358,13 @@ def relocate_binary(path_names, old_dir, new_dir, allow_root): modify_macho_object(path_name, rpaths, deps, idpath, new_rpaths, new_deps, new_idpath) - replace_prefix_bin(path_name, old_dir, new_dir) - + if len(new_dir) <= len(old_dir): + replace_prefix_bin(path_name, old_dir, new_dir) + else: + tty.warn('Cannot do a binary string replacement' + ' with padding for %s' + ' because %s is longer than %s' % + (path_name, new_dir, old_dir)) elif platform.system() == 'Linux': for path_name in path_names: orig_rpaths = get_existing_elf_rpaths(path_name) @@ -355,7 +376,13 @@ def relocate_binary(path_names, old_dir, new_dir, allow_root): new_rpaths = substitute_rpath(n_rpaths, old_dir, new_dir) modify_elf_object(path_name, new_rpaths) - replace_prefix_bin(path_name, old_dir, new_dir) + if len(new_dir) <= len(old_dir): + replace_prefix_bin(path_name, old_dir, new_dir) + else: + tty.warn('Cannot do a binary string replacement' + ' with padding for %s' + ' because %s is longer than %s.' % + (path_name, new_dir, old_dir)) else: tty.die("Relocation not implemented for %s" % platform.system())