codegen: escape string default values to prevent code injection (#8964)

String default values parsed from .fbs schemas are un-escaped by the IDL
parser (e.g., \x22 becomes a raw " byte), but code generators embed these
raw values directly into generated source code string literals. This allows
specially crafted .fbs files to break out of string literals and inject
arbitrary code into generated C++, Rust, TypeScript, and Swift source.

Fix by adding EscapeCodeGenString() helper that re-escapes string content
before embedding, and applying it to all 7 affected injection points across
5 code generators (C++, Rust, TypeScript, Swift, FBS).

Resolves the TODO comments in idl_gen_cpp.cpp and idl_gen_rust.cpp.
diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp
index ffd94e4..9ad18a7 100644
--- a/src/idl_gen_cpp.cpp
+++ b/src/idl_gen_cpp.cpp
@@ -2779,15 +2779,17 @@
         get_call += ">(" + offset_str + ");";
         code_ += get_call;
       } else if (IsString(type) && field.value.constant != "0") {
-        // TODO: Add logic to always convert the string to a valid C++ string
-        // literal by handling string escapes.
+        std::string escaped;
+        flatbuffers::EscapeString(field.value.constant.c_str(),
+                                  field.value.constant.length(), &escaped,
+                                  true, false);
         code_ += "    auto* ptr = {{FIELD_VALUE}};";
         code_ += "    if (ptr) return ptr;";
         code_ += "    static const struct { uint32_t len; const char s[" +
                  NumToString(field.value.constant.length() + 1) +
                  "]; } bfbs_string = { " +
-                 NumToString(field.value.constant.length()) + ", \"" +
-                 field.value.constant + "\" };";
+                 NumToString(field.value.constant.length()) + ", " +
+                 escaped + " };";
         code_ +=
             "    return reinterpret_cast<const ::flatbuffers::String "
             " *>(&bfbs_string);";
@@ -3417,11 +3419,15 @@
             code_.SetValue("CREATE_STRING", "CreateSharedString");
           }
           if (field->value.constant != "0") {
+            std::string escaped;
+            flatbuffers::EscapeString(field->value.constant.c_str(),
+                                      field->value.constant.length(), &escaped,
+                                      true, false);
             code_ +=
                 "  auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
                 "_fbb.{{CREATE_STRING}}({{FIELD_NAME}}) : "
-                "_fbb.{{CREATE_STRING}}(\"" +
-                field->value.constant + "\");";
+                "_fbb.{{CREATE_STRING}}(" +
+                escaped + ");";
           } else {
             code_ +=
                 "  auto {{FIELD_NAME}}__ = {{FIELD_NAME}} ? "
diff --git a/src/idl_gen_fbs.cpp b/src/idl_gen_fbs.cpp
index da42895..0acd7e4 100644
--- a/src/idl_gen_fbs.cpp
+++ b/src/idl_gen_fbs.cpp
@@ -368,7 +368,17 @@
       if (field.value.type.base_type != BASE_TYPE_UTYPE) {
         GenComment(field.doc_comment, &schema, nullptr, "  ");
         schema += "  " + field.name + ":" + GenType(field.value.type);
-        if (field.value.constant != "0") schema += " = " + field.value.constant;
+        if (field.value.constant != "0") {
+          if (IsString(field.value.type)) {
+            std::string escaped;
+            flatbuffers::EscapeString(field.value.constant.c_str(),
+                                      field.value.constant.length(), &escaped,
+                                      true, false);
+            schema += " = " + escaped;
+          } else {
+            schema += " = " + field.value.constant;
+          }
+        }
         std::vector<std::string> attributes;
         if (field.IsRequired()) attributes.push_back("required");
         if (field.key) attributes.push_back("key");
diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp
index 3430a34..d62bbff 100644
--- a/src/idl_gen_rust.cpp
+++ b/src/idl_gen_rust.cpp
@@ -1138,9 +1138,14 @@
         // need one for Rust's Default trait so we use empty string. The usual
         // value of field.value.constant is `0`, which is non-sensical except
         // maybe to c++ (nullptr == 0).
-        // TODO: Escape strings?
-        const std::string defval =
-            field.IsRequired() ? "\"\"" : "\"" + field.value.constant + "\"";
+        std::string defval;
+        if (field.IsRequired()) {
+          defval = "\"\"";
+        } else {
+          flatbuffers::EscapeString(field.value.constant.c_str(),
+                                    field.value.constant.length(), &defval,
+                                    true, false);
+        }
         if (context == kObject) {
           return "alloc::string::ToString::to_string(" + defval + ")";
         }
diff --git a/src/idl_gen_swift.cpp b/src/idl_gen_swift.cpp
index f926aa5..f534ca2 100644
--- a/src/idl_gen_swift.cpp
+++ b/src/idl_gen_swift.cpp
@@ -859,7 +859,10 @@
         break;
 
       case BASE_TYPE_STRING: {
-        const auto default_string = "\"" + SwiftConstant(field) + "\"";
+        const auto sc = SwiftConstant(field);
+        std::string default_string;
+        flatbuffers::EscapeString(sc.c_str(), sc.length(), &default_string,
+                                  true, false);
         code_.SetValue("VALUETYPE", GenType(field.value.type));
         code_.SetValue("CONSTANT", field.IsDefault() ? default_string : "nil");
         code_ += GenReaderMainBody(is_required) + GenOffset() +
@@ -1649,15 +1652,23 @@
         buffer_constructor.push_back(field_var + " = _t." + field_field);
 
         if (field.IsRequired()) {
-          std::string default_value =
-              field.IsDefault() ? SwiftConstant(field) : "";
-          base_constructor.push_back(field_var + " = \"" + default_value +
-                                     "\"");
+          std::string default_value;
+          if (field.IsDefault()) {
+            const auto sc = SwiftConstant(field);
+            flatbuffers::EscapeString(sc.c_str(), sc.length(), &default_value,
+                                      true, false);
+          } else {
+            default_value = "\"\"";
+          }
+          base_constructor.push_back(field_var + " = " + default_value);
           break;
         }
         if (field.IsDefault() && !field.IsRequired()) {
-          std::string value = field.IsDefault() ? SwiftConstant(field) : "nil";
-          base_constructor.push_back(field_var + " = \"" + value + "\"");
+          const auto sc = SwiftConstant(field);
+          std::string value;
+          flatbuffers::EscapeString(sc.c_str(), sc.length(), &value,
+                                    true, false);
+          base_constructor.push_back(field_var + " = " + value);
         }
         break;
       }
diff --git a/src/idl_gen_ts.cpp b/src/idl_gen_ts.cpp
index 9bd00d0..8d02b8e 100644
--- a/src/idl_gen_ts.cpp
+++ b/src/idl_gen_ts.cpp
@@ -529,7 +529,11 @@
         if (value.constant == "0" || value.constant == "null") {
           return "null";
         } else {
-          return "\"" + value.constant + "\"";
+          std::string escaped;
+          flatbuffers::EscapeString(value.constant.c_str(),
+                                    value.constant.length(), &escaped,
+                                    true, false);
+          return escaped;
         }
       }
       case BASE_TYPE_UNION: