Skip to content

write_str_simd_fastest can accidentally write strings twice. under miri #62

@EmilyMatt

Description

@EmilyMatt

In write_str_simd_fastest, When avx2 and sse4.2 do not exist
we fall to

#[cfg(not(feature = "portable"))]
return write_string_rust(writer, string);
#[cfg(feature = "portable")]
return write_str_simd_portable(writer, string);

write_str_simd_portable ends with

*string = string.get_unchecked(idx..);
Ok(())

However write_string_rust simply does

writer.write_all(string)

The issue arises in write_string_content, which does this:

#[inline]
    fn write_string_content(&mut self, string: &str) -> io::Result<()> {
        let mut string = string.as_bytes();
        unsafe {
            // Looking at the table above the lower 5 bits are entirely
            // quote characters that gives us a bitmask of 0x1f for that
            // region, only quote (`"`) and backslash (`\`) are not in
            // this range.
            stry!(self.write_str_simd(&mut string));
        }
        write_string_rust(self.get_writer(), &mut string)
    }

So in the case where not(feature = "portable"), we write the string, we don't advance it, and then we call write_string_rust again on the not advanced string, unlike the other cases.
This is a weird edge case caused by miri messing with the target detection, I think.
The underlying issue still exists, when compiling with runtime_detection, no portable, and the x86_64 CPU does not have avx or the other feature

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions