Browse Source

Support NULL pointers in '%s'

glibc, musl, and other common libc implementations allow a NULL pointer
to be passed to the `%s` specifier, and format it as "(null)". This
patch adds support to printf-compat to do the same.
Dan Gohman 1 year ago
parent
commit
9cb3d5e884
3 changed files with 13 additions and 1 deletions
  1. 2 0
      CHANGELOG.md
  2. 10 1
      src/parser.rs
  3. 1 0
      src/tests.rs

+ 2 - 0
CHANGELOG.md

@@ -4,6 +4,8 @@
 
 * Remove dependency on `alloc`.
   <https://github.com/lights0123/printf-compat/pull/25>
+* Output `(null)` when a null pointer is formatted with `%s`.
+  <https://github.com/lights0123/printf-compat/pull/31>
 
 ## 0.2.0 (July 14, 2025)
 

+ 10 - 1
src/parser.rs

@@ -187,7 +187,16 @@ pub unsafe fn format(
                     value: args.arg(),
                     format: DoubleFormat::Hex.set_upper(ch.is_ascii_uppercase()),
                 },
-                b's' => Specifier::String(CStr::from_ptr(args.arg())),
+                b's' => {
+                    let arg: *mut c_char = args.arg();
+                    // As a common extension supported by glibc, musl, and
+                    // others, format a NULL pointer as "(null)".
+                    if arg.is_null() {
+                        Specifier::Bytes(b"(null)")
+                    } else {
+                        Specifier::String(CStr::from_ptr(arg))
+                    }
+                }
                 b'c' => Specifier::Char(args.arg::<u32>() as u8),
                 b'p' => Specifier::Pointer(args.arg()),
                 b'n' => Specifier::WriteBytesWritten(written, args.arg()),

+ 1 - 0
src/tests.rs

@@ -73,6 +73,7 @@ fn test_str() {
         assert_eq_fmt!(c_str!("%10.4s"), c_str!("world"));
         assert_eq_fmt!(c_str!("%-10.4s"), c_str!("world"));
         assert_eq_fmt!(c_str!("%-10s"), c_str!("world"));
+        assert_eq_fmt!(c_str!("%s"), null_mut::<c_char>());
     }
 }