Skip to content

Commit f6cf559

Browse files
Jake ChampionJakeChampion
authored andcommitted
fix: when appending headers, if the set if set-cookie then make sure that each value is sent as a separate header to the host
1 parent 04999ae commit f6cf559

File tree

1 file changed

+68
-6
lines changed

1 file changed

+68
-6
lines changed

c-dependencies/js-compute-runtime/js-compute-builtins.cpp

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3062,6 +3062,54 @@ bool get_header_value_for_name(JSContext *cx, HandleObject self, HandleValue nam
30623062
return true;
30633063
}
30643064

3065+
std::string_view special_chars = "=,;";
3066+
3067+
std::vector<std::string_view> splitCookiesString(std::string_view cookiesString) {
3068+
std::vector<std::string_view> cookiesStrings;
3069+
std::size_t currentPosition = 0; // Current position in the string
3070+
std::size_t start; // Start position of the current cookie
3071+
char currentChar; // Current character in the string
3072+
std::size_t lastComma; // Position of the last comma found
3073+
std::size_t nextStart; // Position of the start of the next cookie
3074+
3075+
// Iterate over the string and split it into cookies.
3076+
while (currentPosition < cookiesString.length()) {
3077+
start = currentPosition;
3078+
3079+
// Iterate until we find a comma that might be used as a separator.
3080+
while ((currentPosition = cookiesString.find_first_of(",", currentPosition)) !=
3081+
std::string_view::npos) {
3082+
currentChar = cookiesString.at(currentPosition);
3083+
// ',' is a cookie separator only if we later have '=', before having ';' or ','
3084+
lastComma = currentPosition;
3085+
nextStart = ++currentPosition;
3086+
3087+
// Check if the next sequence of characters is a non-special character followed by an equals
3088+
// sign.
3089+
currentPosition = cookiesString.find_first_of(special_chars, currentPosition);
3090+
3091+
// If the current character is an equals sign, we have found a cookie separator.
3092+
if (currentPosition != std::string_view::npos && cookiesString.at(currentPosition) == '=') {
3093+
// currentPosition is inside the next cookie, so back up and return it.
3094+
currentPosition = nextStart;
3095+
cookiesStrings.push_back(cookiesString.substr(start, lastComma - start));
3096+
start = currentPosition;
3097+
} else {
3098+
// The cookie contains ';' or ',' as part of the value
3099+
// so we need to keep accumulating characters
3100+
currentPosition = lastComma + 1;
3101+
}
3102+
}
3103+
3104+
// If we reach the end of the string without finding a separator, add the last cookie to the
3105+
// vector.
3106+
if (currentPosition >= cookiesString.length()) {
3107+
cookiesStrings.push_back(cookiesString.substr(start, cookiesString.length() - start));
3108+
}
3109+
}
3110+
return cookiesStrings;
3111+
}
3112+
30653113
static bool ensure_all_header_values_from_handle(JSContext *cx, HandleObject self,
30663114
HandleObject backing_map) {
30673115
if (!lazy_values(self))
@@ -3108,19 +3156,33 @@ bool append_header_value(JSContext *cx, HandleObject self, HandleValue name, Han
31083156

31093157
// Ensure that any host-side values have been applied JS-side.
31103158
RootedValue v(cx);
3111-
if (!ensure_value_for_header(cx, self, normalized_name, &v))
3159+
if (!ensure_value_for_header(cx, self, normalized_name, &v)) {
31123160
return false;
3161+
}
31133162

31143163
Mode mode = detail::mode(self);
31153164
if (mode != Mode::Standalone) {
31163165
AppendHeaderOperation *op;
3117-
if (mode == Mode::ProxyToRequest)
3166+
if (mode == Mode::ProxyToRequest) {
31183167
op = (AppendHeaderOperation *)xqd_req_header_append;
3119-
else
3168+
} else {
31203169
op = (AppendHeaderOperation *)xqd_resp_header_append;
3121-
if (!HANDLE_RESULT(
3122-
cx, op(handle(self), name_chars.get(), name_len, value_chars.get(), value_len))) {
3123-
return false;
3170+
}
3171+
std::string_view name(name_chars.get(), name_len);
3172+
if (name == "set-cookie") {
3173+
std::string_view value(value_chars.get(), value_len);
3174+
auto values = splitCookiesString(value);
3175+
for (auto value : values) {
3176+
auto result = op(handle(self), name_chars.get(), name_len, value.data(), value.length());
3177+
if (!HANDLE_RESULT(cx, result)) {
3178+
return false;
3179+
}
3180+
}
3181+
} else {
3182+
auto result = op(handle(self), name_chars.get(), name_len, value_chars.get(), value_len);
3183+
if (!HANDLE_RESULT(cx, result)) {
3184+
return false;
3185+
}
31243186
}
31253187
}
31263188

0 commit comments

Comments
 (0)