MCPcopy Create free account
hub / github.com/Tiiny-AI/PowerInfer / fs_validate_filename

Function fs_validate_filename

smallthinker/common/common.cpp:691–768  ·  view source on GitHub ↗

Validate if a filename is safe to use To validate a full path, split the path by the OS-specific path separator, and validate each part with this function

Source from the content-addressed store, hash-verified

689// Validate if a filename is safe to use
690// To validate a full path, split the path by the OS-specific path separator, and validate each part with this function
691bool fs_validate_filename(const std::string & filename) {
692 if (!filename.length()) {
693 // Empty filename invalid
694 return false;
695 }
696 if (filename.length() > 255) {
697 // Limit at common largest possible filename on Linux filesystems
698 // to avoid unnecessary further validation
699 // (On systems with smaller limits it will be caught by the OS)
700 return false;
701 }
702
703 std::u32string filename_utf32;
704 try {
705#if defined(__clang__)
706 // disable C++17 deprecation warning for std::codecvt_utf8
707# pragma clang diagnostic push
708# pragma clang diagnostic ignored "-Wdeprecated-declarations"
709#endif
710 std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;
711
712#if defined(__clang__)
713# pragma clang diagnostic pop
714#endif
715
716 filename_utf32 = converter.from_bytes(filename);
717
718 // If the reverse conversion mismatches, it means overlong UTF-8 sequences were used,
719 // or invalid encodings were encountered. Reject such attempts
720 std::string filename_reencoded = converter.to_bytes(filename_utf32);
721 if (filename_reencoded != filename) {
722 return false;
723 }
724 } catch (const std::exception &) {
725 return false;
726 }
727
728 // Check for forbidden codepoints:
729 // - Control characters
730 // - Unicode equivalents of illegal characters
731 // - UTF-16 surrogate pairs
732 // - UTF-8 replacement character
733 // - Byte order mark (BOM)
734 // - Illegal characters: / \ : * ? " < > |
735 for (char32_t c : filename_utf32) {
736 if (c <= 0x1F // Control characters (C0)
737 || c == 0x7F // Control characters (DEL)
738 || (c >= 0x80 && c <= 0x9F) // Control characters (C1)
739 || c == 0xFF0E // Fullwidth Full Stop (period equivalent)
740 || c == 0x2215 // Division Slash (forward slash equivalent)
741 || c == 0x2216 // Set Minus (backslash equivalent)
742 || (c >= 0xD800 && c <= 0xDFFF) // UTF-16 surrogate pairs
743 || c == 0xFFFD // Replacement Character (UTF-8)
744 || c == 0xFEFF // Byte Order Mark (BOM)
745 || c == '/' || c == '\\' || c == ':' || c == '*' // Illegal characters
746 || c == '?' || c == '"' || c == '<' || c == '>' || c == '|') {
747 return false;
748 }

Callers 1

mainFunction · 0.85

Calls 2

lengthMethod · 0.80
findMethod · 0.80

Tested by

no test coverage detected