Reject null items and empty members during HTTP structured headers serialization.

* Fail serialization cleanly when encountering a default-constructed `ParameterizedMember` instead of crashing via `QUICHE_CHECK(false)`.
* Reject null `Item` parameter values during serialization instead of serializing them as boolean `true` (a holdover from Draft 09).

Neither case can be produced by the RFC 8941 (`kFinal`) parsers (`ParseItem`, `ParseList`, `ParseDictionary`), and an audit of all Google3 callers of `SerializeItem`, `SerializeList`, and `SerializeDictionary` confirms that no caller constructs or serializes either case.

PiperOrigin-RevId: 1000923381
diff --git a/quiche/common/structured_headers.cc b/quiche/common/structured_headers.cc
index f7a24a5..671a67e 100644
--- a/quiche/common/structured_headers.cc
+++ b/quiche/common/structured_headers.cc
@@ -738,10 +738,7 @@
     return value.Visit(absl::Overload{
         [&](const ParameterizedItem& value) { return WriteItem(value); },
         [&](const InnerList& value) { return WriteInnerList(value); },
-        [](std::monostate) {
-          QUICHE_CHECK(false);
-          return false;
-        },
+        [](std::monostate) { return false; },
     });
   }
 
@@ -763,7 +760,7 @@
     for (const auto& [param_name, param_value] : value) {
       output_.push_back(';');
       if (!WriteKey(param_name)) return false;
-      if (param_value.is_null() || IsBooleanTrue(param_value)) continue;
+      if (IsBooleanTrue(param_value)) continue;
       output_.push_back('=');
       if (!WriteBareItem(param_value)) return false;
     }
diff --git a/quiche/common/structured_headers_test.cc b/quiche/common/structured_headers_test.cc
index 84f13ff..ca88e12 100644
--- a/quiche/common/structured_headers_test.cc
+++ b/quiche/common/structured_headers_test.cc
@@ -660,6 +660,7 @@
     const char* name;
     const List value;
   } bad_lists[] = {
+      {"Default-constructed member", {ParameterizedMember()}},
       {"Null item as member", {{Item(), {}}}},
       {"Unserializable item as member", {{Token("\n"), {}}}},
       {"Key is empty", {{Token("abc"), {Param("", 1)}}}},
@@ -669,6 +670,7 @@
        {{Token("abc"), {Param("a\x7f", 1)}}}},
       {"Key contains disallowed characters",
        {{Token("abc"), {Param("a:", 1)}}}},
+      {"Param value is null", {{Token("abc"), {NullParam("a")}}}},
       {"Param value is unserializable", {{Token("abc"), {{"a", Token("\n")}}}}},
       {"Inner list contains unserializable item",
        {{std::vector<ParameterizedItem>{{Token("\n"), {}}}, {}}}},
@@ -784,9 +786,13 @@
     const char* name;
     const Dictionary value;
   } bad_dictionaries[] = {
+      {"Default-constructed member",
+       Dictionary{{{"abc", ParameterizedMember()}}}},
       {"Unserializable dict key", Dictionary{{{"ABC", {Token("abc"), {}}}}}},
       {"Dictionary item is unserializable",
        Dictionary{{{"abc", {Token("abc="), {}}}}}},
+      {"Param value is null",
+       Dictionary{{{"abc", {Token("abc"), {NullParam("a")}}}}}},
       {"Param value is unserializable",
        Dictionary{{{"abc", {Token("abc"), {{"a", Token("\n")}}}}}}},
       {"Dictionary inner-list contains unserializable item",