Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: warn about `bindgen` versions 0.66.0 and 0.66.1

`bindgen` versions 0.66.0 and 0.66.1 panic due to C string literals with
NUL characters [1]:

panicked at .cargo/registry/src/index.crates.io-6f17d22bba15001f/bindgen-0.66.0/codegen/mod.rs:717:71:
called `Result::unwrap()` on an `Err` value: FromBytesWithNulError { kind: InteriorNul(4) }

Thus, in preparation for supporting several `bindgen` versions, add a
version check to warn the user about it.

Since some distributions may have patched it (e.g. Debian did [2]),
check if that seems to be the case (after the version check matches),
in order to avoid printing a warning in that case.

We could make it an error, but 1) it is going to fail anyway later
in the build, 2) we would disable `RUST`, which is also painful, 3)
someone could have patched it in a way that still makes our extra check
fail (however unlikely), 4) the interior NUL may go away in the headers
(however unlikely). Thus just warn about it so that users know why it
is failing.

In addition, add a couple tests for the new cases.

Link: https://github.com/rust-lang/rust-bindgen/pull/2567 [1]
Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1069047 [2]
Link: https://lore.kernel.org/r/20240709160615.998336-11-ojeda@kernel.org
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

+38 -3
+13
scripts/rust_is_available.sh
··· 161 161 echo >&2 "***" 162 162 exit 1 163 163 fi 164 + if [ "$rust_bindings_generator_cversion" -eq 6600 ] || 165 + [ "$rust_bindings_generator_cversion" -eq 6601 ]; then 166 + # Distributions may have patched the issue (e.g. Debian did). 167 + if ! "$BINDGEN" $(dirname $0)/rust_is_available_bindgen_0_66.h >/dev/null; then 168 + echo >&2 "***" 169 + echo >&2 "*** Rust bindings generator '$BINDGEN' versions 0.66.0 and 0.66.1 may not" 170 + echo >&2 "*** work due to a bug (https://github.com/rust-lang/rust-bindgen/pull/2567)," 171 + echo >&2 "*** unless patched (like Debian's)." 172 + echo >&2 "*** Your version: $rust_bindings_generator_version" 173 + echo >&2 "***" 174 + warning=1 175 + fi 176 + fi 164 177 165 178 # Check that the `libclang` used by the Rust bindings generator is suitable. 166 179 #
+2
scripts/rust_is_available_bindgen_0_66.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #define A "\0"
+23 -3
scripts/rust_is_available_test.py
··· 54 54 """) 55 55 56 56 @classmethod 57 - def generate_bindgen(cls, version_stdout, libclang_stderr): 57 + def generate_bindgen(cls, version_stdout, libclang_stderr, version_0_66_patched=False): 58 58 if libclang_stderr is None: 59 59 libclang_case = f"raise SystemExit({cls.bindgen_default_bindgen_libclang_failure_exit_code})" 60 60 else: 61 61 libclang_case = f"print({repr(libclang_stderr)}, file=sys.stderr)" 62 62 63 + if version_0_66_patched: 64 + version_0_66_case = "pass" 65 + else: 66 + version_0_66_case = "raise SystemExit(1)" 67 + 63 68 return cls.generate_executable(f"""#!/usr/bin/env python3 64 69 import sys 65 70 if "rust_is_available_bindgen_libclang.h" in " ".join(sys.argv): 66 71 {libclang_case} 72 + elif "rust_is_available_bindgen_0_66.h" in " ".join(sys.argv): 73 + {version_0_66_case} 67 74 else: 68 75 print({repr(version_stdout)}) 69 76 """) 70 77 71 78 @classmethod 72 - def generate_bindgen_version(cls, stdout): 73 - return cls.generate_bindgen(stdout, cls.bindgen_default_bindgen_libclang_stderr) 79 + def generate_bindgen_version(cls, stdout, version_0_66_patched=False): 80 + return cls.generate_bindgen(stdout, cls.bindgen_default_bindgen_libclang_stderr, version_0_66_patched) 74 81 75 82 @classmethod 76 83 def generate_bindgen_libclang_failure(cls): ··· 237 230 bindgen = self.generate_bindgen_version("bindgen 0.50.0") 238 231 result = self.run_script(self.Expected.FAILURE, { "BINDGEN": bindgen }) 239 232 self.assertIn(f"Rust bindings generator '{bindgen}' is too old.", result.stderr) 233 + 234 + def test_bindgen_bad_version_0_66_0_and_0_66_1(self): 235 + for version in ("0.66.0", "0.66.1"): 236 + with self.subTest(version=version): 237 + bindgen = self.generate_bindgen_version(f"bindgen {version}") 238 + result = self.run_script(self.Expected.SUCCESS_WITH_WARNINGS, { "BINDGEN": bindgen }) 239 + self.assertIn(f"Rust bindings generator '{bindgen}' versions 0.66.0 and 0.66.1 may not", result.stderr) 240 + 241 + def test_bindgen_bad_version_0_66_0_and_0_66_1_patched(self): 242 + for version in ("0.66.0", "0.66.1"): 243 + with self.subTest(version=version): 244 + bindgen = self.generate_bindgen_version(f"bindgen {version}", True) 245 + result = self.run_script(self.Expected.SUCCESS, { "BINDGEN": bindgen }) 240 246 241 247 def test_bindgen_libclang_failure(self): 242 248 bindgen = self.generate_bindgen_libclang_failure()