Files
AnyPS5/docs/dev/debt/libSceHttp.md
T
Dean 291cb22c04 Merge pull request #9066 from orezraey/fix/http-status-line-measured-ps5
fix(libSceHttp): parse status lines past lineLen as measured on a PS5
2026-10-23 15:36:50 +13:00

15 KiB

libSceHttp technical debt

Silent stubs

  • libSceHttp - no request reaches the network, so sceHttpSetResponseHeaderMaxSize has no response header to limit, sceHttpSetRecvBlockSize ((int id, u32 blockSize) as in shadPS4) no response body to read in blocks and sceHttpRedirectCacheFlush no redirect to forget; sceHttpsUnloadCert returns success like sceHttpsLoadCert, which keeps no certificate; sceHttpSetRedirectCallback and sceHttpSetCookieRecvCallback accept callbacks that are never called, sceHttpsSetSslVersion has no TLS connection to configure and sceHttpsGetSslError reports error 0 with detail 0; sceHttpSetAuthInfoCallback accepts a callback that is never called, as no server asks for authentication; sceHttpsGetCaList and sceHttpsFreeCaList report an empty CA list (certs null, certsNum 0) and return 0, as no CA store is kept, and a null list returns ERROR_INVALID_VALUE; unlike shadPS4 they do not check that http_ctx_id is a live context nor that the library is initialised, and sceHttpsFreeCaList also nulls certs, which shadPS4 leaves untouched. The signatures and the { void* certs; int certsNum; } layout follow shadPS4 (PS4), not confirmed on a PS5 title
  • HTTP options without a network (libSceHttp) - sceHttpCacheRedirectedConnectionEnabled, sceHttpsEnableOptionPrivate and sceHttpsDisableOptionPrivate return 0 for a live template, connection or request and keep nothing, since no request reaches the network; the private options refuse flags outside 0x2dff with ERROR_INVALID_VALUE before they look at the id, and sceHttpAbortRequestForce does what sceHttpAbortRequest does. Signatures, the mask and the order of the checks follow shadPS4 (PS4), not measured on a PS5
  • sceHttpSetProxy (libSceHttp) - returns 0 for a live template, connection or request and keeps nothing, since no request reaches the network. The signature (id, HTTP proxy conf, WLAN proxy conf, host, port) and the order of the checks (ERROR_BEFORE_INIT, then ERROR_INVALID_VALUE for a null host, then ERROR_INVALID_ID) follow shadPS4 (PS4), which stores the proxy; not measured on a PS5

Unknown function info

  • HTTP object options (libSceHttp) - a template starts with redirects followed, blocking calls and no Accept-Encoding: gzip, and a connection or request copies its parent's options when it is created. The signatures of the option calls, these defaults, the copying and the order of the checks (BEFORE_INIT first; the last sceHttpTerm ends every object's options) follow shadPS4 (PS4) and are not measured on a PS5. sceHttpSetDefaultAcceptEncodingGZIPEnabled sets the gzip value for templates created later in that context, where shadPS4 keeps one value for the library, and sceHttpUnsetEpoll takes a template or connection id, where shadPS4 looks only at requests. The options change no request, as none reaches the network

  • sceHttpGetConnectionStat (libSceHttp) - connection and request diagnostic signatures are recovered; their outputs contain four and three 32-bit words, respectively. Field semantics remain incomplete. Epoll setters/getters distinguish a 32-bit epoll ID from a pointer-sized handle, and use a pointer-sized user argument. The supplied firmware getter dispatch does not handle the pointer-handle selector used by GetEpoll, so its intended successful behavior is not recoverable from this implementation.

  • sceHttpSetCookieEnabled - the two-argument signature and 0/1 enable values follow VitaSDK and shadPS4; PPSA01521 passes 0 to disable cookies. Disabling succeeds because the offline HTTP backend has no cookie engine; enabling throws. Invalid enable values use the same error as sceHttpSetInflateGZIPEnabled. Like the existing offline HTTP setters, the handle is not validated; requests still fail with the network error. Console behavior is unverified

  • sceHttpParseResponseHeader (libSceHttp) - signature follows SharpProspero; the result, value bounds and error codes follow a payload process on a PS5 (firmware 13.60). Unmeasured there: a bare carriage return, and vertical tab or form feed around the value, which are skipped as blanks before it as before. A value end above INT_MAX throws instead of wrapping

  • sceHttpParseStatusLine (libSceHttp) - follows a payload process on a PS5 (firmware 13.60) for 124 lines and lengths. As on the console, lineLen is only checked to be at least 8 and to leave the 3 code digits (lineLen - index < 3 in unsigned arithmetic): the version digits and the . and space after them are read past lineLen, and the line feed is searched up to and including the byte at lineLen, so a length that stops right before the line feed still parses. When the version ends past lineLen both subtractions wrap and the search goes on until a line feed; what the console does when none follows in readable memory was not measured

  • sceHttpUriMerge (libSceHttp) - signature follows SharpProspero; results, errors and require (the base's sceHttpUriParse size plus 2 and twice the two string lengths, also for a reference copied unchanged) follow a payload process on a PS5 (firmware 13.60). A reference with an authority (// after an optional scheme) is copied unchanged; any other, including mailto:x, http:d, ?q and #f, is appended unswept to the base path up to its last /, and the base query and fragment are dropped. A reference that sceHttpUriParse rejects returns that error, which was not measured.

  • sceHttpUriParse (libSceHttp) - follows a payload process on a PS5 (firmware 13.60) for every ASCII byte inside a scheme, userinfo and hostname, and for letters, digits, +, - and . at the start of a scheme, where a digit ends it; other bytes at the start of a scheme are taken as they are inside one. The userinfo ends at the first @ after bytes from the RFC 3986 userinfo set; a hostname is letters, digits, -, _ and . without a leading ., and the first byte outside it starts the path instead of failing (http://bad host/ has the host bad and the path host/). A port is up to 5 digits that end at / or the end, at most 65536, which reads as 0; an empty port takes 443 for a scheme starting with https, 80 for one starting with http (case-insensitive) and 0 otherwise. The path is swept as sceHttpUriSweepPath does, while the pool keeps room for the unswept path. With a pool too small the console returns ERROR_OUT_OF_MEMORY, leaves require alone and has already written part of the pool; how much is not known, so nothing is written here.

  • sceHttpUriSweepPath (libSceHttp) - follows a payload process on a PS5 (firmware 13.60), which agrees with the shadPS4 reimplementation of the PS4 library: it is not RFC 3986 5.2.4, a path that doesn't start with / is copied unchanged and a trailing . or .. is kept. Like the console, the byte at srcSize - 1 is read as the / that ends a .. segment, and srcSize == 1 with a leading / writes /; whether it also ends a . segment was not measured, so a . there is still kept as before

  • sceHttpSetResponseHeaderMaxSize, sceHttpRedirectCacheFlush, sceHttpsUnloadCert (libSceHttp) - signatures follow shadPS4 (PS4); no PS5 reference has them

  • sceHttpSetRequestStatusCallback - the three-argument ABI follows shadPS4. Registrations and user data are retained and removed on request deletion; the offline backend never dispatches callbacks. Invalid ids return 0x80431100, an uncited assumption, not a verified console error. Handle hierarchy, inheritance and deleted-handle validation remain incomplete; callback statuses and dispatch timing are unknown.

  • sceHttpSetRedirectCallback, sceHttpSetCookieRecvCallback, sceHttpsSetSslVersion, sceHttpsGetSslError (libSceHttp) - signatures follow shadPS4 (PS4), which only logs and returns 0; a null errNum or detail in sceHttpsGetSslError is assumed to return SCE_HTTP_ERROR_INVALID_VALUE like sceHttpGetLastErrno

  • sceHttpSetAuthInfoCallback (libSceHttp) - signature and callback type follow shadPS4 (PS4); no PS5 reference has them. The id is not checked, as in the other libSceHttp setters

  • sceHttpWaitRequest (libSceHttp) - the timeout is assumed to be in microseconds and a negative timeout to wait without limit; the invalid-value error for a null handle or event array or a non-positive event count is assumed, not measured. No request is ever pending, so a wait returns 0 events when its timeout passes

  • sceHttpUriCopy (libSceHttp) - unverified: whether the strings are written before the size check, which a short pool hides by ending cleared. The rest follows a payload process on a PS5 (firmware 13.60): the arguments are (out, src, pool, prepare, require) as in the disassembly; the whole output and all prepare pool bytes are cleared before the source is read, so a source that is the output or lies in the pool copies as empty; the scheme, hostname, path, username and password are copied in that order with terminators, a null one as empty, and the port, while the query, fragment and opaque flag stay 0; a short pool returns 0x80431022 and leaves require alone; a null source returns 0x80433060, and no output or pool with a null require 0x804311FE

  • sceHttpDbgEnableProfile (libSceHttp) - the export is absent from the supplied native module; its signature remains unresolved.

  • sceHttpDbgSetPrintf returns constant success without consuming arguments in the supplied module; the callback contract remains unresolved.

  • sceHttpDbgShowStat (libSceHttp) - the native diagnostic consumes no arguments; it prints library state. The throwing implementation remains unchanged.

  • sceHttpDbgShowConnectionStat (libSceHttp) - the native diagnostic consumes no arguments; it prints library state. The throwing implementation remains unchanged.

  • sceHttpDbgShowRequestStat (libSceHttp) - the native diagnostic consumes no arguments; it prints library state. The throwing implementation remains unchanged.

  • sceHttpDbgShowMemoryPoolStat (libSceHttp) - the native diagnostic consumes no arguments; it prints library state. The throwing implementation remains unchanged.

Functional

  • sceHttpUriParse, sceHttpUriBuild, sceHttpUriMerge - bytes 0x80 to 0xFF were measured only as 0x80, 0xC3 and 0xFF in a hostname; the others, and any of them in a scheme or userinfo, are taken as the measured ASCII bytes outside those sets are. ASCII classification and scheme case folding are independent of the host locale. A bracketed host such as [::1] is parsed, merged and built without its brackets, as a PS5 (firmware 13.60) does; a PS4 (firmware 10.71) takes no bracketed host (http://[::1]x/ has an empty host and the path [::1]x/) and keeps [::1]:80 in a merge, as measured in #9058, so this follows the PS5 only.

  • sceHttpUriEscape escapes every byte except the ASCII unreserved set in RFC 3986 section 2.3, independently of the host locale. Console behaviour for non-ASCII input remains unmeasured.

  • sceHttpAuthCacheFlush, sceHttpCookieFlush (libSceHttp) - the context-id signatures follow SharpProspero, and the NIDs zzB0StvRab4 and seCvUt91WHY match shadPS4. The offline backend never stores authentication credentials or cookies, so flushing a live context succeeds with empty caches. Calls return BEFORE_INIT (0x80431001) when no context is alive and INVALID_ID (0x80431100) for an unknown, deleted or non-context handle, following the existing context lifecycle checks. These error codes and their precedence have not been measured on PS5 hardware; shadPS4 only stubs these calls. Network-backed caches remain unimplemented.

  • sceHttpAbortWaitRequest, sceHttpWaitRequest (libSceHttp) - the abort takes only the epoll handle, as in Orbital and SharpProspero; behaviour and error codes follow shadPS4 (PS4), not confirmed on a PS5 title or hardware. An abort stays set: every later wait on the handle, a poll included, returns SCE_HTTP_ERROR_ABORTED (0x80431080) until the handle is destroyed. A wait woken by sceHttpDestroyEpoll, or by the sceHttpTerm that ends the last context, returns 0 events. The epoll calls return BEFORE_INIT (0x80431001) while no sceHttpInit context is alive and INVALID_ID (0x80431100) for an unknown context or handle, and sceHttpTerm returns the same errors instead of succeeding for any id. Handles are pointers, so a stale handle whose address a newer epoll reuses is taken as that epoll