diff --git a/.pipelines/fasttrack/FasttrackMergeNotifier.yml b/.pipelines/fasttrack/FasttrackMergeNotifier.yml index 912b2eff6b3..1bd04497b62 100644 --- a/.pipelines/fasttrack/FasttrackMergeNotifier.yml +++ b/.pipelines/fasttrack/FasttrackMergeNotifier.yml @@ -15,6 +15,8 @@ extends: template: v2/OneBranch.NonOfficial.CrossPlat.yml@templates parameters: featureFlags: + LinuxHostVersion: + Network: R1 runOnHost: true globalSdl: credscan: diff --git a/.pipelines/prchecks/DevPRCheck.yml b/.pipelines/prchecks/DevPRCheck.yml index 5deaebbf4f5..abf5dc176a1 100644 --- a/.pipelines/prchecks/DevPRCheck.yml +++ b/.pipelines/prchecks/DevPRCheck.yml @@ -25,6 +25,9 @@ variables: extends: template: v2/OneBranch.NonOfficial.CrossPlat.yml@templates parameters: + featureFlags: + LinuxHostVersion: + Network: R1 globalSdl: credscan: suppressionsFile: .config/CredScanSuppressions.json diff --git a/.pipelines/prchecks/FastTrackPRCheck.yml b/.pipelines/prchecks/FastTrackPRCheck.yml index 39cdccfe52c..24c8790a109 100644 --- a/.pipelines/prchecks/FastTrackPRCheck.yml +++ b/.pipelines/prchecks/FastTrackPRCheck.yml @@ -25,6 +25,9 @@ variables: extends: template: v2/OneBranch.NonOfficial.CrossPlat.yml@templates parameters: + featureFlags: + LinuxHostVersion: + Network: R1 globalSdl: credscan: suppressionsFile: .config/CredScanSuppressions.json diff --git a/SPECS/ceph/CVE-2024-47866.patch b/SPECS/ceph/CVE-2024-47866.patch new file mode 100644 index 00000000000..eb35f7d94ae --- /dev/null +++ b/SPECS/ceph/CVE-2024-47866.patch @@ -0,0 +1,33 @@ +From a22a0dbb1d46322007ac4b4e87854ba2ccc8335a Mon Sep 17 00:00:00 2001 +From: Suyash Dongre +Date: Wed, 20 Aug 2025 23:22:41 +0530 +Subject: [PATCH] Check if `HTTP_X_AMZ_COPY_SOURCE` header is empty + +The issue was that the `HTTP_X_AMZ_COPY_SOURCE` header could be present but empty (i.e., an empty string rather than NULL). The code only checked if the pointer was not NULL, but didn't verify that the string had content. When an empty string was passed to RGWCopyObj::parse_copy_location(), it would eventually try to access name_str[0] on an empty string, causing a crash. + +Fixes: https://tracker.ceph.com/issues/72669 + +Signed-off-by: Suyash Dongre +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: https://patch-diff.githubusercontent.com/raw/ceph/ceph/pull/65159.patch +--- + src/rgw/rgw_op.cc | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc +index 71fb198..68f74b7 100644 +--- a/src/rgw/rgw_op.cc ++++ b/src/rgw/rgw_op.cc +@@ -5240,6 +5240,9 @@ bool RGWCopyObj::parse_copy_location(const std::string_view& url_src, + params_str = url_src.substr(pos + 1); + } + ++ if (name_str.empty()) { ++ return false; ++ } + if (name_str[0] == '/') // trim leading slash + name_str.remove_prefix(1); + +-- +2.45.4 + diff --git a/SPECS/ceph/ceph.spec b/SPECS/ceph/ceph.spec index 190142fd2fb..d32cfdfe070 100644 --- a/SPECS/ceph/ceph.spec +++ b/SPECS/ceph/ceph.spec @@ -5,7 +5,7 @@ Summary: User space components of the Ceph file system Name: ceph Version: 18.2.2 -Release: 11%{?dist} +Release: 12%{?dist} License: LGPLv2 and LGPLv3 and CC-BY-SA and GPLv2 and Boost and BSD and MIT and Public Domain and GPLv3 and ASL-2.0 URL: https://ceph.io/ Vendor: Microsoft Corporation @@ -31,6 +31,7 @@ Patch16: CVE-2020-14378.patch Patch17: CVE-2025-52555.patch Patch18: CVE-2024-48916.patch Patch19: CVE-2025-9648.patch +Patch20: CVE-2024-47866.patch # # Copyright (C) 2004-2019 The Ceph Project Developers. See COPYING file # at the top-level directory of this distribution and at @@ -2021,6 +2022,9 @@ exit 0 %config %{_sysconfdir}/prometheus/ceph/ceph_default_alerts.yml %changelog +* Thu Nov 13 2025 Azure Linux Security Servicing Account - 18.2.2-12 +- Patch for CVE-2024-47866 + * Fri Oct 03 2025 Azure Linux Security Servicing Account - 18.2.2-11 - Patch for CVE-2025-9648 @@ -2030,7 +2034,7 @@ exit 0 * Tue Jul 01 2025 Azure Linux Security Servicing Account - 18.2.2-9 - Patch for CVE-2025-52555 -* Wed 16 Apr 2025 Archana Shettigar - 18.2.2-8 +* Wed Apr 16 2025 Archana Shettigar - 18.2.2-8 - Patch CVE-2020-14378 * Thu Apr 10 2025 Kanishk Bansal - 18.2.2-7 diff --git a/SPECS/containerd2/CVE-2024-25621.patch b/SPECS/containerd2/CVE-2024-25621.patch new file mode 100644 index 00000000000..d07a78a1297 --- /dev/null +++ b/SPECS/containerd2/CVE-2024-25621.patch @@ -0,0 +1,111 @@ +From 46223b256bfb3f42e193d947d1b1ef551260749f Mon Sep 17 00:00:00 2001 +From: Akihiro Suda +Date: Mon, 27 Oct 2025 16:42:59 +0900 +Subject: [PATCH] Fix directory permissions + +- Create /var/lib/containerd with 0o700 (was: 0o711). +- Create config.TempDir with 0o700 (was: 0o711). +- Create /run/containerd/io.containerd.grpc.v1.cri with 0o700 (was: 0o755). +- Create /run/containerd/io.containerd.sandbox.controller.v1.shim with 0o700 (was: 0o711). +- Leave /run/containerd and /run/containerd/io.containerd.runtime.v2.task created with 0o711, + as required by userns-remapped containers. + /run/containerd/io.containerd.runtime.v2.task// is created with: + - 0o700 for non-userns-remapped containers + - 0o710 for userns-remapped containers with the remapped root group as the owner group. + +Signed-off-by: Akihiro Suda +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: https://github.com/containerd/containerd/commit/7c59e8e9e970d38061a77b586b23655c352bfec5.patch +--- + cmd/containerd/server/server.go | 14 ++++++++++++-- + core/runtime/v2/task_manager.go | 2 ++ + plugins/cri/runtime/plugin.go | 7 +++++++ + plugins/sandbox/controller.go | 6 +++++- + 4 files changed, 26 insertions(+), 3 deletions(-) + +diff --git a/cmd/containerd/server/server.go b/cmd/containerd/server/server.go +index 9f38cb3..c9e3698 100644 +--- a/cmd/containerd/server/server.go ++++ b/cmd/containerd/server/server.go +@@ -81,10 +81,16 @@ func CreateTopLevelDirectories(config *srvconfig.Config) error { + return errors.New("root and state must be different paths") + } + +- if err := sys.MkdirAllWithACL(config.Root, 0o711); err != nil { ++ if err := sys.MkdirAllWithACL(config.Root, 0o700); err != nil { ++ return err ++ } ++ // chmod is needed for upgrading from an older release that created the dir with 0o711 ++ if err := os.Chmod(config.Root, 0o700); err != nil { + return err + } + ++ // For supporting userns-remapped containers, the state dir cannot be just mkdired with 0o700. ++ // Each of plugins creates a dedicated directory beneath the state dir with appropriate permission bits. + if err := sys.MkdirAllWithACL(config.State, 0o711); err != nil { + return err + } +@@ -99,7 +105,11 @@ func CreateTopLevelDirectories(config *srvconfig.Config) error { + } + + if config.TempDir != "" { +- if err := sys.MkdirAllWithACL(config.TempDir, 0o711); err != nil { ++ if err := sys.MkdirAllWithACL(config.TempDir, 0o700); err != nil { ++ return err ++ } ++ // chmod is needed for upgrading from an older release that created the dir with 0o711 ++ if err := os.Chmod(config.Root, 0o700); err != nil { + return err + } + if runtime.GOOS == "windows" { +diff --git a/core/runtime/v2/task_manager.go b/core/runtime/v2/task_manager.go +index f396ced..024763a 100644 +--- a/core/runtime/v2/task_manager.go ++++ b/core/runtime/v2/task_manager.go +@@ -74,6 +74,8 @@ func init() { + shimManager := shimManagerI.(*ShimManager) + root, state := ic.Properties[plugins.PropertyRootDir], ic.Properties[plugins.PropertyStateDir] + for _, d := range []string{root, state} { ++ // root: the parent of this directory is created as 0o700, not 0o711. ++ // state: the parent of this directory is created as 0o711 too, so as to support userns-remapped containers. + if err := os.MkdirAll(d, 0711); err != nil { + return nil, err + } +diff --git a/plugins/cri/runtime/plugin.go b/plugins/cri/runtime/plugin.go +index adc64d9..07f64a1 100644 +--- a/plugins/cri/runtime/plugin.go ++++ b/plugins/cri/runtime/plugin.go +@@ -91,6 +91,13 @@ func initCRIRuntime(ic *plugin.InitContext) (interface{}, error) { + rootDir := filepath.Join(containerdRootDir, "io.containerd.grpc.v1.cri") + containerdStateDir := filepath.Dir(ic.Properties[plugins.PropertyStateDir]) + stateDir := filepath.Join(containerdStateDir, "io.containerd.grpc.v1.cri") ++ if err := os.MkdirAll(stateDir, 0o700); err != nil { ++ return nil, err ++ } ++ // chmod is needed for upgrading from an older release that created the dir with 0o755 ++ if err := os.Chmod(stateDir, 0o700); err != nil { ++ return nil, err ++ } + c := criconfig.Config{ + RuntimeConfig: *pluginConfig, + ContainerdRootDir: containerdRootDir, +diff --git a/plugins/sandbox/controller.go b/plugins/sandbox/controller.go +index aec9cc3..165f2e8 100644 +--- a/plugins/sandbox/controller.go ++++ b/plugins/sandbox/controller.go +@@ -68,7 +68,11 @@ func init() { + state := ic.Properties[plugins.PropertyStateDir] + root := ic.Properties[plugins.PropertyRootDir] + for _, d := range []string{root, state} { +- if err := os.MkdirAll(d, 0711); err != nil { ++ if err := os.MkdirAll(d, 0700); err != nil { ++ return nil, err ++ } ++ // chmod is needed for upgrading from an older release that created the dir with 0o711 ++ if err := os.Chmod(d, 0o700); err != nil { + return nil, err + } + } +-- +2.45.4 + diff --git a/SPECS/containerd2/containerd2.spec b/SPECS/containerd2/containerd2.spec index 8bc7b48f0bf..bc76e52ba3e 100644 --- a/SPECS/containerd2/containerd2.spec +++ b/SPECS/containerd2/containerd2.spec @@ -5,7 +5,7 @@ Summary: Industry-standard container runtime Name: %{upstream_name}2 Version: 2.0.0 -Release: 14%{?dist} +Release: 15%{?dist} License: ASL 2.0 Group: Tools/Container URL: https://www.containerd.io @@ -23,6 +23,7 @@ Patch3: CVE-2025-22872.patch Patch4: CVE-2025-47291.patch Patch5: multi-snapshotters-support.patch Patch6: tardev-support.patch +Patch7: CVE-2024-25621.patch %{?systemd_requires} BuildRequires: golang < 1.25 @@ -98,6 +99,9 @@ fi %dir /opt/containerd/lib %changelog +* Tue Nov 11 2025 Azure Linux Security Servicing Account - 2.0.0-15 +- Patch for CVE-2024-25621 + * Sun Aug 31 2025 Andrew Phelps - 2.0.0-14 - Set BR for golang to < 1.25 diff --git a/SPECS/docker-buildx/CVE-2025-47913.patch b/SPECS/docker-buildx/CVE-2025-47913.patch new file mode 100644 index 00000000000..3c6870e8401 --- /dev/null +++ b/SPECS/docker-buildx/CVE-2025-47913.patch @@ -0,0 +1,51 @@ +From e5db42e32d99478b5f123a78f9e93b9a69e32abc Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Tue, 18 Nov 2025 15:59:55 +0000 +Subject: [PATCH] ssh/agent: return an error for unexpected message types + +Previously, receiving an unexpected message type in response to a key +listing or a signing request could cause a panic due to a failed type +assertion. + +This change adds a default case to the type switch in order to detect +and explicitly handle unknown or invalid message types, returning a +descriptive error instead of crashing. + +Fixes golang/go#75178 + +Reviewed-by: backport +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://github.com/golang/crypto/commit/559e062ce8bfd6a39925294620b50906ca2a6f95.patch +--- + vendor/golang.org/x/crypto/ssh/agent/client.go | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go +index fecba8e..6dc73e0 100644 +--- a/vendor/golang.org/x/crypto/ssh/agent/client.go ++++ b/vendor/golang.org/x/crypto/ssh/agent/client.go +@@ -430,8 +430,9 @@ func (c *client) List() ([]*Key, error) { + return keys, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to list keys") ++ default: ++ return nil, fmt.Errorf("agent: failed to list keys, unexpected message type %T", msg) + } +- panic("unreachable") + } + + // Sign has the agent sign the data using a protocol 2 key as defined +@@ -462,8 +463,9 @@ func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFl + return &sig, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to sign challenge") ++ default: ++ return nil, fmt.Errorf("agent: failed to sign challenge, unexpected message type %T", msg) + } +- panic("unreachable") + } + + // unmarshal parses an agent message in packet, returning the parsed +-- +2.45.4 + diff --git a/SPECS/docker-buildx/docker-buildx.spec b/SPECS/docker-buildx/docker-buildx.spec index 5e366d2a757..8406bfb0a56 100644 --- a/SPECS/docker-buildx/docker-buildx.spec +++ b/SPECS/docker-buildx/docker-buildx.spec @@ -4,7 +4,7 @@ Summary: A Docker CLI plugin for extended build capabilities with BuildKi Name: docker-buildx # update "commit_hash" above when upgrading version Version: 0.14.0 -Release: 7%{?dist} +Release: 8%{?dist} License: ASL 2.0 Group: Tools/Container Vendor: Microsoft Corporation @@ -16,6 +16,7 @@ Patch1: CVE-2024-45338.patch Patch2: CVE-2025-22869.patch Patch3: CVE-2025-0495.patch Patch4: CVE-2025-22872.patch +Patch5: CVE-2025-47913.patch BuildRequires: bash BuildRequires: golang < 1.25 @@ -49,6 +50,9 @@ install -m 755 buildx "%{buildroot}%{_libexecdir}/docker/cli-plugins/docker-buil %{_libexecdir}/docker/cli-plugins/docker-buildx %changelog +* Tue Nov 18 2025 Azure Linux Security Servicing Account - 0.14.0-8 +- Patch for CVE-2025-47913 + * Sun Aug 31 2025 Andrew Phelps - 0.14.0-7 - Set BR for golang to < 1.25 diff --git a/SPECS/docker-compose/CVE-2025-47913.patch b/SPECS/docker-compose/CVE-2025-47913.patch new file mode 100644 index 00000000000..b50b85e81b2 --- /dev/null +++ b/SPECS/docker-compose/CVE-2025-47913.patch @@ -0,0 +1,50 @@ +From 3a083d7126710d186760b49c440ce07bdb9a0f27 Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Tue, 18 Nov 2025 15:58:07 +0000 +Subject: [PATCH] ssh/agent: return an error for unexpected message types + +Previously, receiving an unexpected message type in response to a key +listing or a signing request could cause a panic due to a failed type +assertion. + +This change adds a default case to the type switch in order to detect +and explicitly handle unknown or invalid message types, returning a +descriptive error instead of crashing. + +Fixes golang/go#75178 + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://github.com/golang/crypto/commit/559e062ce8bfd6a39925294620b50906ca2a6f95.patch +--- + vendor/golang.org/x/crypto/ssh/agent/client.go | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go +index fecba8e..6dc73e0 100644 +--- a/vendor/golang.org/x/crypto/ssh/agent/client.go ++++ b/vendor/golang.org/x/crypto/ssh/agent/client.go +@@ -430,8 +430,9 @@ func (c *client) List() ([]*Key, error) { + return keys, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to list keys") ++ default: ++ return nil, fmt.Errorf("agent: failed to list keys, unexpected message type %T", msg) + } +- panic("unreachable") + } + + // Sign has the agent sign the data using a protocol 2 key as defined +@@ -462,8 +463,9 @@ func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFl + return &sig, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to sign challenge") ++ default: ++ return nil, fmt.Errorf("agent: failed to sign challenge, unexpected message type %T", msg) + } +- panic("unreachable") + } + + // unmarshal parses an agent message in packet, returning the parsed +-- +2.45.4 + diff --git a/SPECS/docker-compose/docker-compose.spec b/SPECS/docker-compose/docker-compose.spec index 3426e112ded..f18cdd164e7 100644 --- a/SPECS/docker-compose/docker-compose.spec +++ b/SPECS/docker-compose/docker-compose.spec @@ -1,7 +1,7 @@ Summary: Define and run multi-container applications with Docker Name: docker-compose Version: 2.27.0 -Release: 5%{?dist} +Release: 6%{?dist} License: ASL 2.0 Vendor: Microsoft Corporation Distribution: Azure Linux @@ -17,6 +17,7 @@ Patch1: CVE-2024-45338.patch Patch2: CVE-2025-22869.patch Patch3: CVE-2024-10846.patch Patch4: CVE-2025-22872.patch +Patch5: CVE-2025-47913.patch BuildRequires: golang Requires: docker-cli Obsoletes: moby-compose < %{version}-%{release} @@ -49,6 +50,9 @@ install -D -m0755 bin/build/docker-compose %{buildroot}/%{_libexecdir}/docker/cl %{_libexecdir}/docker/cli-plugins/docker-compose %changelog +* Tue Nov 18 2025 Azure Linux Security Servicing Account - 2.27.0-6 +- Patch for CVE-2025-47913 + * Wed Apr 23 2025 Jyoti Kanase - 2.27.0-5 - Patch CVE-2025-22872 diff --git a/SPECS/kubernetes/CVE-2025-52881.patch b/SPECS/kubernetes/CVE-2025-52881.patch new file mode 100644 index 00000000000..0af85081276 --- /dev/null +++ b/SPECS/kubernetes/CVE-2025-52881.patch @@ -0,0 +1,81 @@ +From ae90c15f3b77d996b6fed1f5003ce3c407ee5e62 Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Mon, 24 Nov 2025 05:56:47 +0000 +Subject: [PATCH] vendor(runc): remove EnsureProcHandle function and its uses; + drop unnecessary procfs checks in apparmor and utils_unix + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://github.com/opencontainers/runc/commit/b3dd1bc562ed9996d1a0f249e056c16624046d28.diff +--- + .../libcontainer/apparmor/apparmor_linux.go | 5 ----- + .../runc/libcontainer/utils/utils_unix.go | 17 ----------------- + 2 files changed, 22 deletions(-) + +diff --git a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go +index 8b1483c7..daa9f7c8 100644 +--- a/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go ++++ b/vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_linux.go +@@ -6,7 +6,6 @@ import ( + "os" + "sync" + +- "github.com/opencontainers/runc/libcontainer/utils" + ) + + var ( +@@ -40,10 +39,6 @@ func setProcAttr(attr, value string) error { + } + defer f.Close() + +- if err := utils.EnsureProcHandle(f); err != nil { +- return err +- } +- + _, err = f.WriteString(value) + return err + } +diff --git a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go +index bf3237a2..c3acf21b 100644 +--- a/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go ++++ b/vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go +@@ -4,7 +4,6 @@ + package utils + + import ( +- "fmt" + "os" + "strconv" + _ "unsafe" // for go:linkname +@@ -12,18 +11,6 @@ import ( + "golang.org/x/sys/unix" + ) + +-// EnsureProcHandle returns whether or not the given file handle is on procfs. +-func EnsureProcHandle(fh *os.File) error { +- var buf unix.Statfs_t +- if err := unix.Fstatfs(int(fh.Fd()), &buf); err != nil { +- return fmt.Errorf("ensure %s is on procfs: %w", fh.Name(), err) +- } +- if buf.Type != unix.PROC_SUPER_MAGIC { +- return fmt.Errorf("%s is not on procfs", fh.Name()) +- } +- return nil +-} +- + type fdFunc func(fd int) + + // fdRangeFrom calls the passed fdFunc for each file descriptor that is open in +@@ -35,10 +22,6 @@ func fdRangeFrom(minFd int, fn fdFunc) error { + } + defer fdDir.Close() + +- if err := EnsureProcHandle(fdDir); err != nil { +- return err +- } +- + fdList, err := fdDir.Readdirnames(-1) + if err != nil { + return err +-- +2.45.4 + diff --git a/SPECS/kubernetes/kubernetes.spec b/SPECS/kubernetes/kubernetes.spec index 83b68ae22a5..388b9e8151a 100644 --- a/SPECS/kubernetes/kubernetes.spec +++ b/SPECS/kubernetes/kubernetes.spec @@ -10,7 +10,7 @@ Summary: Microsoft Kubernetes Name: kubernetes Version: 1.30.10 -Release: 14%{?dist} +Release: 15%{?dist} License: ASL 2.0 Vendor: Microsoft Corporation Distribution: Azure Linux @@ -27,6 +27,7 @@ Patch5: CVE-2024-51744.patch Patch6: CVE-2025-30204.patch Patch7: CVE-2025-22872.patch Patch8: CVE-2025-4563.patch +Patch9: CVE-2025-52881.patch BuildRequires: flex-devel BuildRequires: glibc-static >= 2.38-15%{?dist} BuildRequires: golang < 1.25 @@ -278,6 +279,9 @@ fi %{_exec_prefix}/local/bin/pause %changelog +* Mon Nov 24 2025 Azure Linux Security Servicing Account - 1.30.10-15 +- Patch for CVE-2025-52881 + * Thu Oct 23 2025 Kanishk Bansal - 1.30.10-14 - Bump to rebuild with updated glibc diff --git a/SPECS/kubevirt/CVE-2025-47913.patch b/SPECS/kubevirt/CVE-2025-47913.patch new file mode 100644 index 00000000000..65d524aab8b --- /dev/null +++ b/SPECS/kubevirt/CVE-2025-47913.patch @@ -0,0 +1,50 @@ +From 7d6da779448c01f323cf73e38a18850660c95d2d Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Tue, 18 Nov 2025 16:23:38 +0000 +Subject: [PATCH] ssh/agent: return an error for unexpected message types + +Previously, receiving an unexpected message type in response to a key +listing or a signing request could cause a panic due to a failed type +assertion. + +This change adds a default case to the type switch in order to detect +and explicitly handle unknown or invalid message types, returning a +descriptive error instead of crashing. + +Fixes golang/go#75178 + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://github.com/golang/crypto/commit/559e062ce8bfd6a39925294620b50906ca2a6f95.patch +--- + vendor/golang.org/x/crypto/ssh/agent/client.go | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go +index 106708d..410e21b 100644 +--- a/vendor/golang.org/x/crypto/ssh/agent/client.go ++++ b/vendor/golang.org/x/crypto/ssh/agent/client.go +@@ -430,8 +430,9 @@ func (c *client) List() ([]*Key, error) { + return keys, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to list keys") ++ default: ++ return nil, fmt.Errorf("agent: failed to list keys, unexpected message type %T", msg) + } +- panic("unreachable") + } + + // Sign has the agent sign the data using a protocol 2 key as defined +@@ -462,8 +463,9 @@ func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFl + return &sig, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to sign challenge") ++ default: ++ return nil, fmt.Errorf("agent: failed to sign challenge, unexpected message type %T", msg) + } +- panic("unreachable") + } + + // unmarshal parses an agent message in packet, returning the parsed +-- +2.45.4 + diff --git a/SPECS/kubevirt/kubevirt.spec b/SPECS/kubevirt/kubevirt.spec index c0a7d5b2156..d31769ebb95 100644 --- a/SPECS/kubevirt/kubevirt.spec +++ b/SPECS/kubevirt/kubevirt.spec @@ -20,7 +20,7 @@ Summary: Container native virtualization Name: kubevirt Version: 1.5.0 -Release: 5%{?dist} +Release: 6%{?dist} License: ASL 2.0 Vendor: Microsoft Corporation Distribution: Azure Linux @@ -32,6 +32,7 @@ Source0: https://github.com/kubevirt/kubevirt/archive/refs/tags/v%{versio # correctly. Patch0: CVE-2025-22869.patch Patch1: CVE-2025-22872.patch +Patch2: CVE-2025-47913.patch %global debug_package %{nil} BuildRequires: swtpm-tools @@ -269,6 +270,9 @@ install -p -m 0644 cmd/virt-launcher/qemu.conf %{buildroot}%{_datadir}/kube-virt %{_bindir}/virt-tests %changelog +* Tue Nov 18 2025 Azure Linux Security Servicing Account - 1.5.0-6 +- Patch for CVE-2025-47913 + * Thu Oct 23 2025 Kanishk Bansal - 1.5.0-5 - Bump to rebuild with updated glibc diff --git a/SPECS/libmicrohttpd/CVE-2025-59777.patch b/SPECS/libmicrohttpd/CVE-2025-59777.patch new file mode 100644 index 00000000000..b4c2f67acec --- /dev/null +++ b/SPECS/libmicrohttpd/CVE-2025-59777.patch @@ -0,0 +1,13142 @@ +From ff13abc1c1d7d2b30d69d5c0bd4a237e1801c50b Mon Sep 17 00:00:00 2001 +From: Christian Grothoff +Date: Tue, 16 Sep 2025 11:00:37 +0200 +Subject: remove broken experimental code + +Upstream Patch Reference: https://git.gnunet.org/libmicrohttpd.git/patch/?id=ff13abc1c1d7d2b30d69d5c0bd4a237e1801c50b +--- + src/Makefile.am | 5 - + src/microhttpd_ws/Makefile.am | 38 - + src/microhttpd_ws/mhd_websocket.c | 2443 ------- + src/microhttpd_ws/sha1.c | 378 - + src/microhttpd_ws/sha1.h | 110 - + src/microhttpd_ws/test_websocket.c | 10105 --------------------------- + 6 files changed, 13079 deletions(-) + delete mode 100644 src/microhttpd_ws/mhd_websocket.c + delete mode 100644 src/microhttpd_ws/sha1.c + delete mode 100644 src/microhttpd_ws/sha1.h + delete mode 100644 src/microhttpd_ws/test_websocket.c + +diff --git a/src/Makefile.am b/src/Makefile.am +index 0d2f49b..bb3cdcb 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -10,11 +10,6 @@ endif + + SUBDIRS = include microhttpd $(curltests) $(zzuftests) . + +-# Finally (last!) also build experimental lib... +-if HAVE_EXPERIMENTAL +-SUBDIRS += microhttpd_ws lib +-endif +- + if BUILD_EXAMPLES + SUBDIRS += examples + endif +diff --git a/src/microhttpd_ws/Makefile.am b/src/microhttpd_ws/Makefile.am +index 1661250..8b13789 100644 +--- a/src/microhttpd_ws/Makefile.am ++++ b/src/microhttpd_ws/Makefile.am +@@ -1,39 +1 @@ +-# This Makefile.am is in the public domain +-AM_CPPFLAGS = \ +- -I$(top_srcdir)/src/include \ +- -I$(top_srcdir)/src/microhttpd + +-AM_CFLAGS = $(HIDDEN_VISIBILITY_CFLAGS) +- +-noinst_DATA = +-MOSTLYCLEANFILES = +- +-SUBDIRS = . +- +-lib_LTLIBRARIES = \ +- libmicrohttpd_ws.la +-libmicrohttpd_ws_la_SOURCES = \ +- sha1.c sha1.h \ +- mhd_websocket.c +-libmicrohttpd_ws_la_CPPFLAGS = \ +- $(AM_CPPFLAGS) $(MHD_LIB_CPPFLAGS) \ +- -DBUILDING_MHD_LIB=1 +-libmicrohttpd_ws_la_CFLAGS = \ +- $(AM_CFLAGS) $(MHD_LIB_CFLAGS) +-libmicrohttpd_ws_la_LDFLAGS = \ +- $(MHD_LIB_LDFLAGS) \ +- $(W32_MHD_LIB_LDFLAGS) \ +- -version-info 0:0:0 +-libmicrohttpd_ws_la_LIBADD = \ +- $(MHD_LIBDEPS) +- +-TESTS = $(check_PROGRAMS) +- +-check_PROGRAMS = \ +- test_websocket +- +-test_websocket_SOURCES = \ +- test_websocket.c +-test_websocket_LDADD = \ +- $(top_builddir)/src/microhttpd_ws/libmicrohttpd_ws.la \ +- $(top_builddir)/src/microhttpd/libmicrohttpd.la +diff --git a/src/microhttpd_ws/mhd_websocket.c b/src/microhttpd_ws/mhd_websocket.c +deleted file mode 100644 +index 935deee..0000000 +--- a/src/microhttpd_ws/mhd_websocket.c ++++ /dev/null +@@ -1,2443 +0,0 @@ +-/* +- This file is part of libmicrohttpd +- Copyright (C) 2021 David Gausmann +- +- This library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- This library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with this library; if not, write to the Free Software +- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +- +-*/ +- +-/** +- * @file microhttpd_ws/mhd_websocket.c +- * @brief Support for the websocket protocol +- * @author David Gausmann +- */ +-#include "platform.h" +-#include "microhttpd.h" +-#include "microhttpd_ws.h" +-#include "sha1.h" +- +-struct MHD_WebSocketStream +-{ +- /* The function pointer to malloc for payload (can be used to use different memory management) */ +- MHD_WebSocketMallocCallback malloc; +- /* The function pointer to realloc for payload (can be used to use different memory management) */ +- MHD_WebSocketReallocCallback realloc; +- /* The function pointer to free for payload (can be used to use different memory management) */ +- MHD_WebSocketFreeCallback free; +- /* A closure for the random number generator (only used for client mode; usually not required) */ +- void *cls_rng; +- /* The random number generator (only used for client mode; usually not required) */ +- MHD_WebSocketRandomNumberGenerator rng; +- /* The flags specified upon initialization. It may alter the behavior of decoding/encoding */ +- int flags; +- /* The current step for the decoder. 0 means start of a frame. */ +- char decode_step; +- /* Specifies whether the stream is valid (1) or not (0), +- if a close frame has been received this is (-1) to indicate that no data frames are allowed anymore */ +- char validity; +- /* The current step of the UTF-8 encoding check in the data payload */ +- char data_utf8_step; +- /* The current step of the UTF-8 encoding check in the control payload */ +- char control_utf8_step; +- /* if != 0 means that we expect a CONTINUATION frame */ +- char data_type; +- /* The start of the current frame (may differ from data_payload for CONTINUATION frames) */ +- char *data_payload_start; +- /* The buffer for the data frame */ +- char *data_payload; +- /* The buffer for the control frame */ +- char *control_payload; +- /* Configuration for the maximum allowed buffer size for payload data */ +- size_t max_payload_size; +- /* The current frame header size */ +- size_t frame_header_size; +- /* The current data payload size (can be greater than payload_size for fragmented frames) */ +- size_t data_payload_size; +- /* The size of the payload of the current frame (control or data) */ +- size_t payload_size; +- /* The processing offset to the start of the payload of the current frame (control or data) */ +- size_t payload_index; +- /* The frame header of the current frame (control or data) */ +- char frame_header[32]; +- /* The mask key of the current frame (control or data); this is 0 if no masking used */ +- char mask_key[4]; +-}; +- +-#define MHD_WEBSOCKET_FLAG_MASK_SERVERCLIENT MHD_WEBSOCKET_FLAG_CLIENT +-#define MHD_WEBSOCKET_FLAG_MASK_FRAGMENTATION \ +- MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS +-#define MHD_WEBSOCKET_FLAG_MASK_GENERATE_CLOSE_FRAMES \ +- MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR +-#define MHD_WEBSOCKET_FLAG_MASK_ALL \ +- (MHD_WEBSOCKET_FLAG_MASK_SERVERCLIENT \ +- | MHD_WEBSOCKET_FLAG_MASK_FRAGMENTATION \ +- | MHD_WEBSOCKET_FLAG_MASK_GENERATE_CLOSE_FRAMES) +- +-enum MHD_WebSocket_Opcode +-{ +- MHD_WebSocket_Opcode_Continuation = 0x0, +- MHD_WebSocket_Opcode_Text = 0x1, +- MHD_WebSocket_Opcode_Binary = 0x2, +- MHD_WebSocket_Opcode_Close = 0x8, +- MHD_WebSocket_Opcode_Ping = 0x9, +- MHD_WebSocket_Opcode_Pong = 0xA +-}; +- +-enum MHD_WebSocket_DecodeStep +-{ +- MHD_WebSocket_DecodeStep_Start = 0, +- MHD_WebSocket_DecodeStep_Length1ofX = 1, +- MHD_WebSocket_DecodeStep_Length1of2 = 2, +- MHD_WebSocket_DecodeStep_Length2of2 = 3, +- MHD_WebSocket_DecodeStep_Length1of8 = 4, +- MHD_WebSocket_DecodeStep_Length2of8 = 5, +- MHD_WebSocket_DecodeStep_Length3of8 = 6, +- MHD_WebSocket_DecodeStep_Length4of8 = 7, +- MHD_WebSocket_DecodeStep_Length5of8 = 8, +- MHD_WebSocket_DecodeStep_Length6of8 = 9, +- MHD_WebSocket_DecodeStep_Length7of8 = 10, +- MHD_WebSocket_DecodeStep_Length8of8 = 11, +- MHD_WebSocket_DecodeStep_Mask1Of4 = 12, +- MHD_WebSocket_DecodeStep_Mask2Of4 = 13, +- MHD_WebSocket_DecodeStep_Mask3Of4 = 14, +- MHD_WebSocket_DecodeStep_Mask4Of4 = 15, +- MHD_WebSocket_DecodeStep_HeaderCompleted = 16, +- MHD_WebSocket_DecodeStep_PayloadOfDataFrame = 17, +- MHD_WebSocket_DecodeStep_PayloadOfControlFrame = 18, +- MHD_WebSocket_DecodeStep_BrokenStream = 99 +-}; +- +-enum MHD_WebSocket_UTF8Result +-{ +- MHD_WebSocket_UTF8Result_Invalid = 0, +- MHD_WebSocket_UTF8Result_Valid = 1, +- MHD_WebSocket_UTF8Result_Incomplete = 2 +-}; +- +-static void +-MHD_websocket_copy_payload (char *dst, +- const char *src, +- size_t len, +- uint32_t mask, +- unsigned long mask_offset); +- +-static int +-MHD_websocket_check_utf8 (const char *buf, +- size_t buf_len, +- int *utf8_step, +- size_t *buf_offset); +- +-static enum MHD_WEBSOCKET_STATUS +-MHD_websocket_decode_header_complete (struct MHD_WebSocketStream *ws, +- char **payload, +- size_t *payload_len); +- +-static enum MHD_WEBSOCKET_STATUS +-MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream *ws, +- char **payload, +- size_t *payload_len); +- +-static char +-MHD_websocket_encode_is_masked (struct MHD_WebSocketStream *ws); +-static char +-MHD_websocket_encode_overhead_size (struct MHD_WebSocketStream *ws, +- size_t payload_len); +- +-static enum MHD_WEBSOCKET_STATUS +-MHD_websocket_encode_data (struct MHD_WebSocketStream *ws, +- const char *payload, +- size_t payload_len, +- int fragmentation, +- char **frame, +- size_t *frame_len, +- char opcode); +- +-static enum MHD_WEBSOCKET_STATUS +-MHD_websocket_encode_ping_pong (struct MHD_WebSocketStream *ws, +- const char *payload, +- size_t payload_len, +- char **frame, +- size_t *frame_len, +- char opcode); +- +-static uint32_t +-MHD_websocket_generate_mask (struct MHD_WebSocketStream *ws); +- +-static uint16_t +-MHD_htons (uint16_t value); +- +-static uint64_t +-MHD_htonll (uint64_t value); +- +- +-/** +- * Checks whether the HTTP version is 1.1 or above. +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_check_http_version (const char *http_version) +-{ +- /* validate parameters */ +- if (NULL == http_version) +- { +- /* Like with the other check routines, */ +- /* NULL is threated as "value not given" and not as parameter error */ +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +- } +- +- /* Check whether the version has a valid format */ +- /* RFC 1945 3.1: The format must be "HTTP/x.x" where x is */ +- /* any digit and must appear at least once */ +- if (('H' != http_version[0]) || +- ('T' != http_version[1]) || +- ('T' != http_version[2]) || +- ('P' != http_version[3]) || +- ('/' != http_version[4])) +- { +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +- } +- +- /* Find the major and minor part of the version */ +- /* RFC 1945 3.1: Both numbers must be threated as separate integers. */ +- /* Leading zeros must be ignored and both integers may have multiple digits */ +- const char *major = NULL; +- const char *dot = NULL; +- size_t i = 5; +- for (;;) +- { +- char c = http_version[i]; +- if (('0' <= c) && ('9' >= c)) +- { +- if ((NULL == major) || +- ((http_version + i == major + 1) && ('0' == *major)) ) +- { +- major = http_version + i; +- } +- ++i; +- } +- else if ('.' == http_version[i]) +- { +- dot = http_version + i; +- ++i; +- break; +- } +- else +- { +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +- } +- } +- const char *minor = NULL; +- const char *end = NULL; +- for (;;) +- { +- char c = http_version[i]; +- if (('0' <= c) && ('9' >= c)) +- { +- if ((NULL == minor) || +- ((http_version + i == minor + 1) && ('0' == *minor)) ) +- { +- minor = http_version + i; +- } +- ++i; +- } +- else if (0 == c) +- { +- end = http_version + i; +- break; +- } +- else +- { +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +- } +- } +- if ((NULL == major) || (NULL == dot) || (NULL == minor) || (NULL == end)) +- { +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +- } +- if ((2 <= dot - major) || ('2' <= *major) || +- (('1' == *major) && ((2 <= end - minor) || ('1' <= *minor))) ) +- { +- return MHD_WEBSOCKET_STATUS_OK; +- } +- +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +-} +- +- +-/** +- * Checks whether the "Connection" request header has the 'Upgrade' token. +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_check_connection_header (const char *connection_header) +-{ +- /* validate parameters */ +- if (NULL == connection_header) +- { +- /* To be compatible with the return value */ +- /* of MHD_lookup_connection_value, */ +- /* NULL is threated as "value not given" and not as parameter error */ +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +- } +- +- /* Check whether the Connection includes an Upgrade token */ +- /* RFC 7230 6.1: Multiple tokens may appear. */ +- /* RFC 7230 3.2.6: Tokens are comma separated */ +- const char *token_start = NULL; +- const char *token_end = NULL; +- for (size_t i = 0; ; ++i) +- { +- char c = connection_header[i]; +- +- /* RFC 7230 3.2.6: The list of allowed characters is a token is: */ +- /* "!" / "#" / "$" / "%" / "&" / "'" / "*" / */ +- /* "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" */ +- /* DIGIT / ALPHA */ +- if (('!' == c) || ('#' == c) || ('$' == c) || ('%' == c) || +- ('&' == c) || ('\'' == c) || ('*' == c) || +- ('+' == c) || ('-' == c) || ('.' == c) || ('^' == c) || +- ('_' == c) || ('`' == c) || ('|' == c) || ('~' == c) || +- (('0' <= c) && ('9' >= c)) || +- (('A' <= c) && ('Z' >= c)) || (('a' <= c) && ('z' >= c)) ) +- { +- /* This is a valid token character */ +- if (NULL == token_start) +- { +- token_start = connection_header + i; +- } +- token_end = connection_header + i + 1; +- } +- else if ((' ' == c) || ('\t' == c)) +- { +- /* White-spaces around tokens will be ignored */ +- } +- else if ((',' == c) || (0 == c)) +- { +- /* Check the token (case-insensitive) */ +- if (NULL != token_start) +- { +- if (7 == (token_end - token_start) ) +- { +- if ( (('U' == token_start[0]) || ('u' == token_start[0])) && +- (('P' == token_start[1]) || ('p' == token_start[1])) && +- (('G' == token_start[2]) || ('g' == token_start[2])) && +- (('R' == token_start[3]) || ('r' == token_start[3])) && +- (('A' == token_start[4]) || ('a' == token_start[4])) && +- (('D' == token_start[5]) || ('d' == token_start[5])) && +- (('E' == token_start[6]) || ('e' == token_start[6])) ) +- { +- /* The token equals to "Upgrade" */ +- return MHD_WEBSOCKET_STATUS_OK; +- } +- } +- } +- if (0 == c) +- { +- break; +- } +- token_start = NULL; +- token_end = NULL; +- } +- else +- { +- /* RFC 7230 3.2.6: Other characters are not allowed */ +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +- } +- } +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +-} +- +- +-/** +- * Checks whether the "Upgrade" request header has the "websocket" keyword. +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_check_upgrade_header (const char *upgrade_header) +-{ +- /* validate parameters */ +- if (NULL == upgrade_header) +- { +- /* To be compatible with the return value */ +- /* of MHD_lookup_connection_value, */ +- /* NULL is threated as "value not given" and not as parameter error */ +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +- } +- +- /* Check whether the Connection includes an Upgrade token */ +- /* RFC 7230 6.1: Multiple tokens may appear. */ +- /* RFC 7230 3.2.6: Tokens are comma separated */ +- const char *keyword_start = NULL; +- const char *keyword_end = NULL; +- for (size_t i = 0; ; ++i) +- { +- char c = upgrade_header[i]; +- +- /* RFC 7230 3.2.6: The list of allowed characters is a token is: */ +- /* "!" / "#" / "$" / "%" / "&" / "'" / "*" / */ +- /* "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" */ +- /* DIGIT / ALPHA */ +- /* We also allow "/" here as the sub-delimiter for the protocol version */ +- if (('!' == c) || ('#' == c) || ('$' == c) || ('%' == c) || +- ('&' == c) || ('\'' == c) || ('*' == c) || +- ('+' == c) || ('-' == c) || ('.' == c) || ('^' == c) || +- ('_' == c) || ('`' == c) || ('|' == c) || ('~' == c) || +- ('/' == c) || +- (('0' <= c) && ('9' >= c)) || +- (('A' <= c) && ('Z' >= c)) || (('a' <= c) && ('z' >= c)) ) +- { +- /* This is a valid token character */ +- if (NULL == keyword_start) +- { +- keyword_start = upgrade_header + i; +- } +- keyword_end = upgrade_header + i + 1; +- } +- else if ((' ' == c) || ('\t' == c)) +- { +- /* White-spaces around tokens will be ignored */ +- } +- else if ((',' == c) || (0 == c)) +- { +- /* Check the token (case-insensitive) */ +- if (NULL != keyword_start) +- { +- if (9 == (keyword_end - keyword_start) ) +- { +- if ( (('W' == keyword_start[0]) || ('w' == keyword_start[0])) && +- (('E' == keyword_start[1]) || ('e' == keyword_start[1])) && +- (('B' == keyword_start[2]) || ('b' == keyword_start[2])) && +- (('S' == keyword_start[3]) || ('s' == keyword_start[3])) && +- (('O' == keyword_start[4]) || ('o' == keyword_start[4])) && +- (('C' == keyword_start[5]) || ('c' == keyword_start[5])) && +- (('K' == keyword_start[6]) || ('k' == keyword_start[6])) && +- (('E' == keyword_start[7]) || ('e' == keyword_start[7])) && +- (('T' == keyword_start[8]) || ('t' == keyword_start[8])) ) +- { +- /* The keyword equals to "websocket" */ +- return MHD_WEBSOCKET_STATUS_OK; +- } +- } +- } +- if (0 == c) +- { +- break; +- } +- keyword_start = NULL; +- keyword_end = NULL; +- } +- else +- { +- /* RFC 7230 3.2.6: Other characters are not allowed */ +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +- } +- } +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +-} +- +- +-/** +- * Checks whether the "Sec-WebSocket-Version" request header +- * equals to "13" +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_check_version_header (const char *version_header) +-{ +- /* validate parameters */ +- if (NULL == version_header) +- { +- /* To be compatible with the return value */ +- /* of MHD_lookup_connection_value, */ +- /* NULL is threated as "value not given" and not as parameter error */ +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +- } +- +- if (('1' == version_header[0]) && +- ('3' == version_header[1]) && +- (0 == version_header[2])) +- { +- /* The version equals to "13" */ +- return MHD_WEBSOCKET_STATUS_OK; +- } +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +-} +- +- +-/** +- * Creates the response for the Sec-WebSocket-Accept header +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_create_accept_header (const char *sec_websocket_key, +- char *sec_websocket_accept) +-{ +- /* initialize output variables for errors cases */ +- if (NULL != sec_websocket_accept) +- *sec_websocket_accept = 0; +- +- /* validate parameters */ +- if (NULL == sec_websocket_accept) +- { +- return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; +- } +- if (NULL == sec_websocket_key) +- { +- /* NULL is not a parameter error, */ +- /* because MHD_lookup_connection_value returns NULL */ +- /* if the header wasn't found */ +- return MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER; +- } +- +- /* build SHA1 hash of the given key and the UUID appended */ +- char sha1[20]; +- const char *suffix = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; +- int length = (int) strlen (sec_websocket_key); +- struct sha1_ctx ctx; +- MHD_SHA1_init (&ctx); +- MHD_SHA1_update (&ctx, (const uint8_t *) sec_websocket_key, length); +- MHD_SHA1_update (&ctx, (const uint8_t *) suffix, 36); +- MHD_SHA1_finish (&ctx, (uint8_t *) sha1); +- +- /* base64 encode that SHA1 hash */ +- /* (simple algorithm here; SHA1 has always 20 bytes, */ +- /* which will always result in a 28 bytes base64 hash) */ +- const char *base64_encoding_table = +- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +- for (int i = 0, j = 0; i < 20;) +- { +- uint32_t octet_a = i < 20 ? (unsigned char) sha1[i++] : 0; +- uint32_t octet_b = i < 20 ? (unsigned char) sha1[i++] : 0; +- uint32_t octet_c = i < 20 ? (unsigned char) sha1[i++] : 0; +- uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; +- +- sec_websocket_accept[j++] = base64_encoding_table[(triple >> 3 * 6) & 0x3F]; +- sec_websocket_accept[j++] = base64_encoding_table[(triple >> 2 * 6) & 0x3F]; +- sec_websocket_accept[j++] = base64_encoding_table[(triple >> 1 * 6) & 0x3F]; +- sec_websocket_accept[j++] = base64_encoding_table[(triple >> 0 * 6) & 0x3F]; +- +- } +- sec_websocket_accept[27] = '='; +- sec_websocket_accept[28] = 0; +- +- return MHD_WEBSOCKET_STATUS_OK; +-} +- +- +-/** +- * Initializes a new websocket stream +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_stream_init (struct MHD_WebSocketStream **ws, +- int flags, +- size_t max_payload_size) +-{ +- return MHD_websocket_stream_init2 (ws, +- flags, +- max_payload_size, +- malloc, +- realloc, +- free, +- NULL, +- NULL); +-} +- +- +-/** +- * Initializes a new websocket stream with +- * additional parameters for allocation functions +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_stream_init2 (struct MHD_WebSocketStream **ws, +- int flags, +- size_t max_payload_size, +- MHD_WebSocketMallocCallback callback_malloc, +- MHD_WebSocketReallocCallback callback_realloc, +- MHD_WebSocketFreeCallback callback_free, +- void *cls_rng, +- MHD_WebSocketRandomNumberGenerator callback_rng) +-{ +- /* initialize output variables for errors cases */ +- if (NULL != ws) +- *ws = NULL; +- +- /* validate parameters */ +- if ((NULL == ws) || +- (0 != (flags & ~MHD_WEBSOCKET_FLAG_MASK_ALL)) || +- ((uint64_t) 0x7FFFFFFFFFFFFFFF < max_payload_size) || +- (NULL == callback_malloc) || +- (NULL == callback_realloc) || +- (NULL == callback_free) || +- ((0 != (flags & MHD_WEBSOCKET_FLAG_CLIENT)) && +- (NULL == callback_rng))) +- { +- return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; +- } +- +- /* allocate stream */ +- struct MHD_WebSocketStream *ws_ = (struct MHD_WebSocketStream *) malloc ( +- sizeof (struct MHD_WebSocketStream)); +- if (NULL == ws_) +- return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; +- +- /* initialize stream */ +- memset (ws_, 0, sizeof (struct MHD_WebSocketStream)); +- ws_->flags = flags; +- ws_->max_payload_size = max_payload_size; +- ws_->malloc = callback_malloc; +- ws_->realloc = callback_realloc; +- ws_->free = callback_free; +- ws_->cls_rng = cls_rng; +- ws_->rng = callback_rng; +- ws_->validity = MHD_WEBSOCKET_VALIDITY_VALID; +- +- /* return stream */ +- *ws = ws_; +- +- return MHD_WEBSOCKET_STATUS_OK; +-} +- +- +-/** +- * Frees a previously allocated websocket stream +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_stream_free (struct MHD_WebSocketStream *ws) +-{ +- /* validate parameters */ +- if (NULL == ws) +- return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; +- +- /* free allocated payload data */ +- if (ws->data_payload) +- ws->free (ws->data_payload); +- if (ws->control_payload) +- ws->free (ws->control_payload); +- +- /* free the stream */ +- free (ws); +- +- return MHD_WEBSOCKET_STATUS_OK; +-} +- +- +-/** +- * Invalidates a websocket stream (no more decoding possible) +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_stream_invalidate (struct MHD_WebSocketStream *ws) +-{ +- /* validate parameters */ +- if (NULL == ws) +- return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; +- +- /* invalidate stream */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- +- return MHD_WEBSOCKET_STATUS_OK; +-} +- +- +-/** +- * Returns whether a websocket stream is valid +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_VALIDITY +-MHD_websocket_stream_is_valid (struct MHD_WebSocketStream *ws) +-{ +- /* validate parameters */ +- if (NULL == ws) +- return MHD_WEBSOCKET_VALIDITY_INVALID; +- +- return ws->validity; +-} +- +- +-/** +- * Decodes incoming data to a websocket frame +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_decode (struct MHD_WebSocketStream *ws, +- const char *streambuf, +- size_t streambuf_len, +- size_t *streambuf_read_len, +- char **payload, +- size_t *payload_len) +-{ +- /* initialize output variables for errors cases */ +- if (NULL != streambuf_read_len) +- *streambuf_read_len = 0; +- if (NULL != payload) +- *payload = NULL; +- if (NULL != payload_len) +- *payload_len = 0; +- +- /* validate parameters */ +- if ((NULL == ws) || +- ((NULL == streambuf) && (0 != streambuf_len)) || +- (NULL == streambuf_read_len) || +- (NULL == payload) || +- (NULL == payload_len) ) +- { +- return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; +- } +- +- /* validate stream validity */ +- if (MHD_WEBSOCKET_VALIDITY_INVALID == ws->validity) +- return MHD_WEBSOCKET_STATUS_STREAM_BROKEN; +- +- /* decode loop */ +- size_t current = 0; +- while (current < streambuf_len) +- { +- switch (ws->decode_step) +- { +- /* start of frame */ +- case MHD_WebSocket_DecodeStep_Start: +- { +- /* The first byte contains the opcode, the fin flag and three reserved bits */ +- if (MHD_WEBSOCKET_VALIDITY_INVALID != ws->validity) +- { +- char opcode = streambuf [current]; +- if (0 != (opcode & 0x70)) +- { +- /* RFC 6455 5.2 RSV1-3: If a reserved flag is set */ +- /* (while it isn't specified by an extension) the communication must fail. */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- switch (opcode & 0x0F) +- { +- case MHD_WebSocket_Opcode_Continuation: +- if (0 == ws->data_type) +- { +- /* RFC 6455 5.4: Continuation frame without previous data frame */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- if (MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES == +- ws->validity) +- { +- /* RFC 6455 5.5.1: After a close frame has been sent, */ +- /* no data frames may be sent (so we don't accept data frames */ +- /* for decoding anymore) */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- break; +- +- case MHD_WebSocket_Opcode_Text: +- case MHD_WebSocket_Opcode_Binary: +- if (0 != ws->data_type) +- { +- /* RFC 6455 5.4: Continuation expected, but new data frame */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- if (MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES == +- ws->validity) +- { +- /* RFC 6455 5.5.1: After a close frame has been sent, */ +- /* no data frames may be sent (so we don't accept data frames */ +- /* for decoding anymore) */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- break; +- +- case MHD_WebSocket_Opcode_Close: +- case MHD_WebSocket_Opcode_Ping: +- case MHD_WebSocket_Opcode_Pong: +- if ((opcode & 0x80) == 0) +- { +- /* RFC 6455 5.4: Control frames may not be fragmented */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- if (MHD_WebSocket_Opcode_Close == (opcode & 0x0F)) +- { +- /* RFC 6455 5.5.1: After a close frame has been sent, */ +- /* no data frames may be sent (so we don't accept data frames */ +- /* for decoding anymore) */ +- ws->validity = +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES; +- } +- break; +- +- default: +- /* RFC 6455 5.2 OPCODE: Only six opcodes are specified. */ +- /* All other are invalid in version 13 of the protocol. */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- } +- ws->frame_header [ws->frame_header_size++] = streambuf [current++]; +- ws->decode_step = MHD_WebSocket_DecodeStep_Length1ofX; +- } +- break; +- +- case MHD_WebSocket_DecodeStep_Length1ofX: +- { +- /* The second byte specifies whether the data is masked and the size */ +- /* (the client MUST mask the payload, the server MUST NOT mask the payload) */ +- char frame_len = streambuf [current]; +- char is_masked = (frame_len & 0x80); +- frame_len &= 0x7f; +- if (MHD_WEBSOCKET_VALIDITY_INVALID != ws->validity) +- { +- if (0 != is_masked) +- { +- if (MHD_WEBSOCKET_FLAG_CLIENT == (ws->flags +- & MHD_WEBSOCKET_FLAG_CLIENT)) +- { +- /* RFC 6455 5.1: All frames from the server must be unmasked */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- } +- else +- { +- if (MHD_WEBSOCKET_FLAG_SERVER == (ws->flags +- & MHD_WEBSOCKET_FLAG_CLIENT)) +- { +- /* RFC 6455 5.1: All frames from the client must be masked */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- } +- if (126 <= frame_len) +- { +- if (0 != (ws->frame_header [0] & 0x08)) +- { +- /* RFC 6455 5.5: Control frames may not have more payload than 125 bytes */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- } +- if (1 == frame_len) +- { +- if (MHD_WebSocket_Opcode_Close == (ws->frame_header [0] & 0x0F)) +- { +- /* RFC 6455 5.5.1: The close frame must have at least */ +- /* two bytes of payload if payload is used */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- } +- } +- ws->frame_header [ws->frame_header_size++] = streambuf [current++]; +- +- if (126 == frame_len) +- { +- ws->decode_step = MHD_WebSocket_DecodeStep_Length1of2; +- } +- else if (127 == frame_len) +- { +- ws->decode_step = MHD_WebSocket_DecodeStep_Length1of8; +- } +- else +- { +- size_t size = (size_t) frame_len; +- if ((SIZE_MAX < size) || +- (ws->max_payload_size && (ws->max_payload_size < size)) ) +- { +- /* RFC 6455 7.4.1 1009: If the message is too big to process, we may close the connection */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_MAXIMUM_ALLOWED_PAYLOAD_SIZE_EXCEEDED, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; +- } +- ws->payload_size = size; +- if (0 != is_masked) +- { +- /* with mask */ +- ws->decode_step = MHD_WebSocket_DecodeStep_Mask1Of4; +- } +- else +- { +- /* without mask */ +- *((uint32_t *) ws->mask_key) = 0; +- ws->decode_step = MHD_WebSocket_DecodeStep_HeaderCompleted; +- } +- } +- } +- break; +- +- /* Payload size first byte of 2 bytes */ +- case MHD_WebSocket_DecodeStep_Length1of2: +- /* Payload size first 7 bytes of 8 bytes */ +- case MHD_WebSocket_DecodeStep_Length1of8: +- case MHD_WebSocket_DecodeStep_Length2of8: +- case MHD_WebSocket_DecodeStep_Length3of8: +- case MHD_WebSocket_DecodeStep_Length4of8: +- case MHD_WebSocket_DecodeStep_Length5of8: +- case MHD_WebSocket_DecodeStep_Length6of8: +- case MHD_WebSocket_DecodeStep_Length7of8: +- /* Mask first 3 bytes of 4 bytes */ +- case MHD_WebSocket_DecodeStep_Mask1Of4: +- case MHD_WebSocket_DecodeStep_Mask2Of4: +- case MHD_WebSocket_DecodeStep_Mask3Of4: +- ws->frame_header [ws->frame_header_size++] = streambuf [current++]; +- ++ws->decode_step; +- break; +- +- /* 2 byte length finished */ +- case MHD_WebSocket_DecodeStep_Length2of2: +- { +- ws->frame_header [ws->frame_header_size++] = streambuf [current++]; +- size_t size = (size_t) MHD_htons ( +- *((uint16_t *) &ws->frame_header [2])); +- if (125 >= size) +- { +- /* RFC 6455 5.2 Payload length: The minimal number of bytes */ +- /* must be used for the length */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- if ((SIZE_MAX < size) || +- (ws->max_payload_size && (ws->max_payload_size < size)) ) +- { +- /* RFC 6455 7.4.1 1009: If the message is too big to process, */ +- /* we may close the connection */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_MAXIMUM_ALLOWED_PAYLOAD_SIZE_EXCEEDED, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; +- } +- ws->payload_size = size; +- if (0 != (ws->frame_header [1] & 0x80)) +- { +- /* with mask */ +- ws->decode_step = MHD_WebSocket_DecodeStep_Mask1Of4; +- } +- else +- { +- /* without mask */ +- *((uint32_t *) ws->mask_key) = 0; +- ws->decode_step = MHD_WebSocket_DecodeStep_HeaderCompleted; +- } +- } +- break; +- +- /* 8 byte length finished */ +- case MHD_WebSocket_DecodeStep_Length8of8: +- { +- ws->frame_header [ws->frame_header_size++] = streambuf [current++]; +- uint64_t size = MHD_htonll (*((uint64_t *) &ws->frame_header [2])); +- if (0x7fffffffffffffff < size) +- { +- /* RFC 6455 5.2 frame-payload-length-63: The length may */ +- /* not exceed 0x7fffffffffffffff */ +- ws->decode_step = MHD_WebSocket_DecodeStep_BrokenStream; +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- if (65535 >= size) +- { +- /* RFC 6455 5.2 Payload length: The minimal number of bytes */ +- /* must be used for the length */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_PROTOCOL_ERROR, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- } +- if ((SIZE_MAX < size) || +- (ws->max_payload_size && (ws->max_payload_size < size)) ) +- { +- /* RFC 6455 7.4.1 1009: If the message is too big to process, */ +- /* we may close the connection */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_MAXIMUM_ALLOWED_PAYLOAD_SIZE_EXCEEDED, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; +- } +- ws->payload_size = (size_t) size; +- +- if (0 != (ws->frame_header [1] & 0x80)) +- { +- /* with mask */ +- ws->decode_step = MHD_WebSocket_DecodeStep_Mask1Of4; +- } +- else +- { +- /* without mask */ +- *((uint32_t *) ws->mask_key) = 0; +- ws->decode_step = MHD_WebSocket_DecodeStep_HeaderCompleted; +- } +- } +- break; +- +- /* mask finished */ +- case MHD_WebSocket_DecodeStep_Mask4Of4: +- ws->frame_header [ws->frame_header_size++] = streambuf [current++]; +- *((uint32_t *) ws->mask_key) = *((uint32_t *) &ws->frame_header [ws-> +- frame_header_size +- - 4]); +- ws->decode_step = MHD_WebSocket_DecodeStep_HeaderCompleted; +- break; +- +- /* header finished */ +- case MHD_WebSocket_DecodeStep_HeaderCompleted: +- /* return or assign either to data or control */ +- { +- int ret = MHD_websocket_decode_header_complete (ws, +- payload, +- payload_len); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- *streambuf_read_len = current; +- return ret; +- } +- } +- break; +- +- /* payload data */ +- case MHD_WebSocket_DecodeStep_PayloadOfDataFrame: +- case MHD_WebSocket_DecodeStep_PayloadOfControlFrame: +- { +- size_t bytes_needed = ws->payload_size - ws->payload_index; +- size_t bytes_remaining = streambuf_len - current; +- size_t bytes_to_take = bytes_needed < bytes_remaining ? bytes_needed : +- bytes_remaining; +- if (0 != bytes_to_take) +- { +- size_t utf8_start = ws->payload_index; +- char *decode_payload = ws->decode_step == +- MHD_WebSocket_DecodeStep_PayloadOfDataFrame ? +- ws->data_payload_start : +- ws->control_payload; +- +- /* copy the new payload data (with unmasking if necessary */ +- MHD_websocket_copy_payload (decode_payload + ws->payload_index, +- &streambuf [current], +- bytes_to_take, +- *((uint32_t *) ws->mask_key), +- (unsigned long) (ws->payload_index +- & 0x03)); +- current += bytes_to_take; +- ws->payload_index += bytes_to_take; +- if (((MHD_WebSocket_DecodeStep_PayloadOfDataFrame == +- ws->decode_step) && +- (MHD_WebSocket_Opcode_Text == ws->data_type)) || +- ((MHD_WebSocket_DecodeStep_PayloadOfControlFrame == +- ws->decode_step) && +- (MHD_WebSocket_Opcode_Close == (ws->frame_header [0] & 0x0f)) && +- (2 < ws->payload_index)) ) +- { +- /* RFC 6455 8.1: We need to check the UTF-8 validity */ +- int utf8_step; +- char *decode_payload_utf8; +- size_t bytes_to_check; +- size_t utf8_error_offset = 0; +- if (MHD_WebSocket_DecodeStep_PayloadOfDataFrame == ws->decode_step) +- { +- utf8_step = ws->data_utf8_step; +- decode_payload_utf8 = decode_payload + utf8_start; +- bytes_to_check = bytes_to_take; +- } +- else +- { +- utf8_step = ws->control_utf8_step; +- if ((MHD_WebSocket_Opcode_Close == (ws->frame_header [0] +- & 0x0f)) && +- (2 > utf8_start) ) +- { +- /* The first two bytes of the close frame are binary content and */ +- /* must be skipped in the UTF-8 check */ +- utf8_start = 2; +- utf8_error_offset = 2; +- } +- decode_payload_utf8 = decode_payload + utf8_start; +- bytes_to_check = bytes_to_take - utf8_start; +- } +- size_t utf8_check_offset = 0; +- int utf8_result = MHD_websocket_check_utf8 (decode_payload_utf8, +- bytes_to_check, +- &utf8_step, +- &utf8_check_offset); +- if (MHD_WebSocket_UTF8Result_Invalid != utf8_result) +- { +- /* memorize current validity check step to continue later */ +- ws->data_utf8_step = utf8_step; +- } +- else +- { +- /* RFC 6455 8.1: We must fail on broken UTF-8 sequence */ +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_MALFORMED_UTF8, +- 0, +- 0, +- payload, +- payload_len); +- } +- *streambuf_read_len = current - bytes_to_take +- + utf8_check_offset + utf8_error_offset; +- return MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR; +- } +- } +- } +- } +- +- if (ws->payload_size == ws->payload_index) +- { +- /* all payload data of the current frame has been received */ +- int ret = MHD_websocket_decode_payload_complete (ws, +- payload, +- payload_len); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- *streambuf_read_len = current; +- return ret; +- } +- } +- break; +- +- case MHD_WebSocket_DecodeStep_BrokenStream: +- *streambuf_read_len = current; +- return MHD_WEBSOCKET_STATUS_STREAM_BROKEN; +- } +- } +- +- /* Special treatment for zero payload length messages */ +- if (MHD_WebSocket_DecodeStep_HeaderCompleted == ws->decode_step) +- { +- int ret = MHD_websocket_decode_header_complete (ws, +- payload, +- payload_len); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- *streambuf_read_len = current; +- return ret; +- } +- } +- switch (ws->decode_step) +- { +- case MHD_WebSocket_DecodeStep_PayloadOfDataFrame: +- case MHD_WebSocket_DecodeStep_PayloadOfControlFrame: +- if (ws->payload_size == ws->payload_index) +- { +- /* all payload data of the current frame has been received */ +- int ret = MHD_websocket_decode_payload_complete (ws, +- payload, +- payload_len); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- *streambuf_read_len = current; +- return ret; +- } +- } +- break; +- } +- *streambuf_read_len = current; +- +- /* more data needed */ +- return MHD_WEBSOCKET_STATUS_OK; +-} +- +- +-static enum MHD_WEBSOCKET_STATUS +-MHD_websocket_decode_header_complete (struct MHD_WebSocketStream *ws, +- char **payload, +- size_t *payload_len) +-{ +- /* assign either to data or control */ +- char opcode = ws->frame_header [0] & 0x0f; +- switch (opcode) +- { +- case MHD_WebSocket_Opcode_Continuation: +- { +- /* validate payload size */ +- size_t new_size_total = ws->payload_size + ws->data_payload_size; +- if ((0 != ws->max_payload_size) && (ws->max_payload_size < +- new_size_total) ) +- { +- /* RFC 6455 7.4.1 1009: If the message is too big to process, */ +- /* we may close the connection */ +- ws->decode_step = MHD_WebSocket_DecodeStep_BrokenStream; +- ws->validity = MHD_WEBSOCKET_VALIDITY_INVALID; +- if (0 != (ws->flags +- & MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR)) +- { +- MHD_websocket_encode_close (ws, +- MHD_WEBSOCKET_CLOSEREASON_MAXIMUM_ALLOWED_PAYLOAD_SIZE_EXCEEDED, +- 0, +- 0, +- payload, +- payload_len); +- } +- return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; +- } +- /* allocate buffer for continued data frame */ +- char *new_buf = NULL; +- if (0 != new_size_total) +- { +- new_buf = ws->realloc (ws->data_payload, new_size_total + 1); +- if (NULL == new_buf) +- { +- return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; +- } +- new_buf [new_size_total] = 0; +- ws->data_payload_start = &new_buf[ws->data_payload_size]; +- } +- else +- { +- ws->data_payload_start = new_buf; +- } +- ws->data_payload = new_buf; +- ws->data_payload_size = new_size_total; +- } +- ws->decode_step = MHD_WebSocket_DecodeStep_PayloadOfDataFrame; +- break; +- +- case MHD_WebSocket_Opcode_Text: +- case MHD_WebSocket_Opcode_Binary: +- /* allocate buffer for data frame */ +- { +- size_t new_size_total = ws->payload_size; +- char *new_buf = NULL; +- if (0 != new_size_total) +- { +- new_buf = ws->malloc (new_size_total + 1); +- if (NULL == new_buf) +- { +- return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; +- } +- new_buf [new_size_total] = 0; +- } +- ws->data_payload = new_buf; +- ws->data_payload_start = new_buf; +- ws->data_payload_size = new_size_total; +- ws->data_type = opcode; +- } +- ws->decode_step = MHD_WebSocket_DecodeStep_PayloadOfDataFrame; +- break; +- +- case MHD_WebSocket_Opcode_Close: +- case MHD_WebSocket_Opcode_Ping: +- case MHD_WebSocket_Opcode_Pong: +- /* allocate buffer for control frame */ +- { +- size_t new_size_total = ws->payload_size; +- char *new_buf = NULL; +- if (0 != new_size_total) +- { +- new_buf = ws->malloc (new_size_total + 1); +- if (NULL == new_buf) +- { +- return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; +- } +- new_buf[new_size_total] = 0; +- } +- ws->control_payload = new_buf; +- } +- ws->decode_step = MHD_WebSocket_DecodeStep_PayloadOfControlFrame; +- break; +- } +- +- return MHD_WEBSOCKET_STATUS_OK; +-} +- +- +-static enum MHD_WEBSOCKET_STATUS +-MHD_websocket_decode_payload_complete (struct MHD_WebSocketStream *ws, +- char **payload, +- size_t *payload_len) +-{ +- /* all payload data of the current frame has been received */ +- char is_continue = MHD_WebSocket_Opcode_Continuation == +- (ws->frame_header [0] & 0x0F); +- char is_fin = ws->frame_header [0] & 0x80; +- if (0 != is_fin) +- { +- /* the frame is complete */ +- if (MHD_WebSocket_DecodeStep_PayloadOfDataFrame == ws->decode_step) +- { +- /* data frame */ +- char data_type = ws->data_type; +- if ((0 != (ws->flags & MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS)) && +- (0 != is_continue)) +- { +- data_type |= 0x40; /* mark as last fragment */ +- } +- *payload = ws->data_payload; +- *payload_len = ws->data_payload_size; +- ws->data_payload = 0; +- ws->data_payload_start = 0; +- ws->data_payload_size = 0; +- ws->decode_step = MHD_WebSocket_DecodeStep_Start; +- ws->payload_index = 0; +- ws->data_type = 0; +- ws->frame_header_size = 0; +- return data_type; +- } +- else +- { +- /* control frame */ +- *payload = ws->control_payload; +- *payload_len = ws->payload_size; +- ws->control_payload = 0; +- ws->decode_step = MHD_WebSocket_DecodeStep_Start; +- ws->payload_index = 0; +- ws->frame_header_size = 0; +- return (ws->frame_header [0] & 0x0f); +- } +- } +- else if (0 != (ws->flags & MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS)) +- { +- /* RFC 6455 5.4: To allow streaming, the user can choose */ +- /* to return fragments */ +- if ((MHD_WebSocket_Opcode_Text == ws->data_type) && +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != ws->data_utf8_step) ) +- { +- /* the last UTF-8 sequence is incomplete, so we keep the start of +- that and only return the part before */ +- size_t given_utf8 = 0; +- switch (ws->data_utf8_step) +- { +- /* one byte given */ +- case MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1: +- case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL1_1OF2: +- case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2: +- case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2: +- case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL1_1OF3: +- case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL2_1OF3: +- case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_1OF3: +- given_utf8 = 1; +- break; +- /* two bytes given */ +- case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2: +- case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3: +- given_utf8 = 2; +- break; +- /* three bytes given */ +- case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_3OF3: +- given_utf8 = 3; +- break; +- } +- size_t new_len = ws->data_payload_size - given_utf8; +- if (0 != new_len) +- { +- char *next_payload = ws->malloc (given_utf8 + 1); +- if (NULL == next_payload) +- { +- return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; +- } +- memcpy (next_payload, +- ws->data_payload_start + ws->payload_index - given_utf8, +- given_utf8); +- next_payload[given_utf8] = 0; +- +- ws->data_payload[new_len] = 0; +- *payload = ws->data_payload; +- *payload_len = new_len; +- ws->data_payload = next_payload; +- ws->data_payload_size = given_utf8; +- } +- else +- { +- *payload = NULL; +- *payload_len = 0; +- } +- ws->decode_step = MHD_WebSocket_DecodeStep_Start; +- ws->payload_index = 0; +- ws->frame_header_size = 0; +- if (0 != is_continue) +- return ws->data_type | 0x20; /* mark as middle fragment */ +- else +- return ws->data_type | 0x10; /* mark as first fragment */ +- } +- else +- { +- /* we simply pass the entire data frame */ +- *payload = ws->data_payload; +- *payload_len = ws->data_payload_size; +- ws->data_payload = 0; +- ws->data_payload_start = 0; +- ws->data_payload_size = 0; +- ws->decode_step = MHD_WebSocket_DecodeStep_Start; +- ws->payload_index = 0; +- ws->frame_header_size = 0; +- if (0 != is_continue) +- return ws->data_type | 0x20; /* mark as middle fragment */ +- else +- return ws->data_type | 0x10; /* mark as first fragment */ +- } +- } +- else +- { +- /* RFC 6455 5.4: We must await a continuation frame to get */ +- /* the remainder of this data frame */ +- ws->decode_step = MHD_WebSocket_DecodeStep_Start; +- ws->frame_header_size = 0; +- ws->payload_index = 0; +- return MHD_WEBSOCKET_STATUS_OK; +- } +-} +- +- +-/** +- * Splits the received close reason +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_split_close_reason (const char *payload, +- size_t payload_len, +- unsigned short *reason_code, +- const char **reason_utf8, +- size_t *reason_utf8_len) +-{ +- /* initialize output variables for errors cases */ +- if (NULL != reason_code) +- *reason_code = MHD_WEBSOCKET_CLOSEREASON_NO_REASON; +- if (NULL != reason_utf8) +- *reason_utf8 = NULL; +- if (NULL != reason_utf8_len) +- *reason_utf8_len = 0; +- +- /* validate parameters */ +- if ((NULL == payload) && (0 != payload_len)) +- return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; +- if (1 == payload_len) +- return MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR; +- if (125 < payload_len) +- return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; +- +- /* decode reason code */ +- if (2 > payload_len) +- { +- if (NULL != reason_code) +- *reason_code = MHD_WEBSOCKET_CLOSEREASON_NO_REASON; +- } +- else +- { +- if (NULL != reason_code) +- *reason_code = MHD_htons (*((uint16_t *) payload)); +- } +- +- /* decode reason text */ +- if (2 >= payload_len) +- { +- if (NULL != reason_utf8) +- *reason_utf8 = NULL; +- if (NULL != reason_utf8_len) +- *reason_utf8_len = 0; +- } +- else +- { +- if (NULL != reason_utf8) +- *reason_utf8 = payload + 2; +- if (NULL != reason_utf8_len) +- *reason_utf8_len = payload_len - 2; +- } +- +- return MHD_WEBSOCKET_STATUS_OK; +-} +- +- +-/** +- * Encodes a text into a websocket text frame +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_encode_text (struct MHD_WebSocketStream *ws, +- const char *payload_utf8, +- size_t payload_utf8_len, +- int fragmentation, +- char **frame, +- size_t *frame_len, +- int *utf8_step) +-{ +- /* initialize output variables for errors cases */ +- if (NULL != frame) +- *frame = NULL; +- if (NULL != frame_len) +- *frame_len = 0; +- if ((NULL != utf8_step) && +- ((MHD_WEBSOCKET_FRAGMENTATION_FIRST == fragmentation) || +- (MHD_WEBSOCKET_FRAGMENTATION_NONE == fragmentation) )) +- { +- /* the old UTF-8 step will be ignored for new fragments */ +- *utf8_step = MHD_WEBSOCKET_UTF8STEP_NORMAL; +- } +- +- /* validate parameters */ +- if ((NULL == ws) || +- ((0 != payload_utf8_len) && (NULL == payload_utf8)) || +- (NULL == frame) || +- (NULL == frame_len) || +- (MHD_WEBSOCKET_FRAGMENTATION_NONE > fragmentation) || +- (MHD_WEBSOCKET_FRAGMENTATION_LAST < fragmentation) || +- ((MHD_WEBSOCKET_FRAGMENTATION_NONE != fragmentation) && +- (NULL == utf8_step)) ) +- { +- return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; +- } +- +- /* check max length */ +- if ((uint64_t) 0x7FFFFFFFFFFFFFFF < (uint64_t) payload_utf8_len) +- { +- return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; +- } +- +- /* check UTF-8 */ +- int utf8_result = MHD_websocket_check_utf8 (payload_utf8, +- payload_utf8_len, +- utf8_step, +- NULL); +- if ((MHD_WebSocket_UTF8Result_Invalid == utf8_result) || +- ((MHD_WebSocket_UTF8Result_Incomplete == utf8_result) && +- (MHD_WEBSOCKET_FRAGMENTATION_NONE == fragmentation)) ) +- { +- return MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR; +- } +- +- /* encode data */ +- return MHD_websocket_encode_data (ws, +- payload_utf8, +- payload_utf8_len, +- fragmentation, +- frame, +- frame_len, +- MHD_WebSocket_Opcode_Text); +-} +- +- +-/** +- * Encodes binary data into a websocket binary frame +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_encode_binary (struct MHD_WebSocketStream *ws, +- const char *payload, +- size_t payload_len, +- int fragmentation, +- char **frame, +- size_t *frame_len) +-{ +- /* initialize output variables for errors cases */ +- if (NULL != frame) +- *frame = NULL; +- if (NULL != frame_len) +- *frame_len = 0; +- +- /* validate parameters */ +- if ((NULL == ws) || +- ((0 != payload_len) && (NULL == payload)) || +- (NULL == frame) || +- (NULL == frame_len) || +- (MHD_WEBSOCKET_FRAGMENTATION_NONE > fragmentation) || +- (MHD_WEBSOCKET_FRAGMENTATION_LAST < fragmentation) ) +- { +- return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; +- } +- +- /* check max length */ +- if ((uint64_t) 0x7FFFFFFFFFFFFFFF < (uint64_t) payload_len) +- { +- return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; +- } +- +- return MHD_websocket_encode_data (ws, +- payload, +- payload_len, +- fragmentation, +- frame, +- frame_len, +- MHD_WebSocket_Opcode_Binary); +-} +- +- +-/** +- * Internal function for encoding text/binary data into a websocket frame +- */ +-static enum MHD_WEBSOCKET_STATUS +-MHD_websocket_encode_data (struct MHD_WebSocketStream *ws, +- const char *payload, +- size_t payload_len, +- int fragmentation, +- char **frame, +- size_t *frame_len, +- char opcode) +-{ +- /* calculate length and masking */ +- char is_masked = MHD_websocket_encode_is_masked (ws); +- size_t overhead_len = MHD_websocket_encode_overhead_size (ws, payload_len); +- size_t total_len = overhead_len + payload_len; +- uint32_t mask = 0 != is_masked ? MHD_websocket_generate_mask (ws) : 0; +- +- /* allocate memory */ +- char *result = ws->malloc (total_len + 1); +- if (NULL == result) +- return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; +- result [total_len] = 0; +- *frame = result; +- *frame_len = total_len; +- +- /* add the opcode */ +- switch (fragmentation) +- { +- case MHD_WEBSOCKET_FRAGMENTATION_NONE: +- *(result++) = 0x80 | opcode; +- break; +- case MHD_WEBSOCKET_FRAGMENTATION_FIRST: +- *(result++) = opcode; +- break; +- case MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING: +- *(result++) = MHD_WebSocket_Opcode_Continuation; +- break; +- case MHD_WEBSOCKET_FRAGMENTATION_LAST: +- *(result++) = 0x80 | MHD_WebSocket_Opcode_Continuation; +- break; +- } +- +- /* add the length */ +- if (126 > payload_len) +- { +- *(result++) = is_masked | (char) payload_len; +- } +- else if (65536 > payload_len) +- { +- *(result++) = is_masked | 126; +- *((uint16_t *) result) = MHD_htons ((uint16_t) payload_len); +- result += 2; +- } +- else +- { +- *(result++) = is_masked | 127; +- *((uint64_t *) result) = MHD_htonll ((uint64_t) payload_len); +- result += 8; +- +- } +- +- /* add the mask */ +- if (0 != is_masked) +- { +- *(result++) = ((char *) &mask)[0]; +- *(result++) = ((char *) &mask)[1]; +- *(result++) = ((char *) &mask)[2]; +- *(result++) = ((char *) &mask)[3]; +- } +- +- /* add the payload */ +- if (0 != payload_len) +- { +- MHD_websocket_copy_payload (result, +- payload, +- payload_len, +- mask, +- 0); +- } +- +- return MHD_WEBSOCKET_STATUS_OK; +-} +- +- +-/** +- * Encodes a websocket ping frame +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_encode_ping (struct MHD_WebSocketStream *ws, +- const char *payload, +- size_t payload_len, +- char **frame, +- size_t *frame_len) +-{ +- /* encode the ping frame */ +- return MHD_websocket_encode_ping_pong (ws, +- payload, +- payload_len, +- frame, +- frame_len, +- MHD_WebSocket_Opcode_Ping); +-} +- +- +-/** +- * Encodes a websocket pong frame +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_encode_pong (struct MHD_WebSocketStream *ws, +- const char *payload, +- size_t payload_len, +- char **frame, +- size_t *frame_len) +-{ +- /* encode the pong frame */ +- return MHD_websocket_encode_ping_pong (ws, +- payload, +- payload_len, +- frame, +- frame_len, +- MHD_WebSocket_Opcode_Pong); +-} +- +- +-/** +- * Internal function for encoding ping/pong frames +- */ +-static enum MHD_WEBSOCKET_STATUS +-MHD_websocket_encode_ping_pong (struct MHD_WebSocketStream *ws, +- const char *payload, +- size_t payload_len, +- char **frame, +- size_t *frame_len, +- char opcode) +-{ +- /* initialize output variables for errors cases */ +- if (NULL != frame) +- *frame = NULL; +- if (NULL != frame_len) +- *frame_len = 0; +- +- /* validate the parameters */ +- if ((NULL == ws) || +- ((0 != payload_len) && (NULL == payload)) || +- (NULL == frame) || +- (NULL == frame_len) ) +- { +- return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; +- } +- +- /* RFC 6455 5.5: Control frames may only have up to 125 bytes of payload data */ +- if (125 < payload_len) +- return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; +- +- /* calculate length and masking */ +- char is_masked = MHD_websocket_encode_is_masked (ws); +- size_t overhead_len = MHD_websocket_encode_overhead_size (ws, payload_len); +- size_t total_len = overhead_len + payload_len; +- uint32_t mask = is_masked != 0 ? MHD_websocket_generate_mask (ws) : 0; +- +- /* allocate memory */ +- char *result = ws->malloc (total_len + 1); +- if (NULL == result) +- return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; +- result [total_len] = 0; +- *frame = result; +- *frame_len = total_len; +- +- /* add the opcode */ +- *(result++) = 0x80 | opcode; +- +- /* add the length */ +- *(result++) = is_masked | (char) payload_len; +- +- /* add the mask */ +- if (0 != is_masked) +- { +- *(result++) = ((char *) &mask)[0]; +- *(result++) = ((char *) &mask)[1]; +- *(result++) = ((char *) &mask)[2]; +- *(result++) = ((char *) &mask)[3]; +- } +- +- /* add the payload */ +- if (0 != payload_len) +- { +- MHD_websocket_copy_payload (result, +- payload, +- payload_len, +- mask, +- 0); +- } +- +- return MHD_WEBSOCKET_STATUS_OK; +-} +- +- +-/** +- * Encodes a websocket close frame +- */ +-_MHD_EXTERN enum MHD_WEBSOCKET_STATUS +-MHD_websocket_encode_close (struct MHD_WebSocketStream *ws, +- unsigned short reason_code, +- const char *reason_utf8, +- size_t reason_utf8_len, +- char **frame, +- size_t *frame_len) +-{ +- /* initialize output variables for errors cases */ +- if (NULL != frame) +- *frame = NULL; +- if (NULL != frame_len) +- *frame_len = 0; +- +- /* validate the parameters */ +- if ((NULL == ws) || +- ((0 != reason_utf8_len) && (NULL == reason_utf8)) || +- (NULL == frame) || +- (NULL == frame_len) || +- ((MHD_WEBSOCKET_CLOSEREASON_NO_REASON != reason_code) && +- (1000 > reason_code)) || +- ((0 != reason_utf8_len) && +- (MHD_WEBSOCKET_CLOSEREASON_NO_REASON == reason_code)) ) +- { +- return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; +- } +- +- /* RFC 6455 5.5: Control frames may only have up to 125 bytes of payload data, */ +- /* but in this case only 123 bytes, because 2 bytes are reserved */ +- /* for the close reason code. */ +- if (123 < reason_utf8_len) +- return MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED; +- +- /* RFC 6455 5.5.1: If close payload data is given, it must be valid UTF-8 */ +- if (0 != reason_utf8_len) +- { +- int utf8_result = MHD_websocket_check_utf8 (reason_utf8, +- reason_utf8_len, +- NULL, +- NULL); +- if (MHD_WebSocket_UTF8Result_Valid != utf8_result) +- return MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR; +- } +- +- /* calculate length and masking */ +- char is_masked = MHD_websocket_encode_is_masked (ws); +- size_t payload_len = (MHD_WEBSOCKET_CLOSEREASON_NO_REASON != reason_code ? +- 2 + reason_utf8_len : 0); +- size_t overhead_len = MHD_websocket_encode_overhead_size (ws, payload_len); +- size_t total_len = overhead_len + payload_len; +- uint32_t mask = is_masked != 0 ? MHD_websocket_generate_mask (ws) : 0; +- +- /* allocate memory */ +- char *result = ws->malloc (total_len + 1); +- if (NULL == result) +- return MHD_WEBSOCKET_STATUS_MEMORY_ERROR; +- result [total_len] = 0; +- *frame = result; +- *frame_len = total_len; +- +- /* add the opcode */ +- *(result++) = 0x88; +- +- /* add the length */ +- *(result++) = is_masked | (char) payload_len; +- +- /* add the mask */ +- if (0 != is_masked) +- { +- *(result++) = ((char *) &mask)[0]; +- *(result++) = ((char *) &mask)[1]; +- *(result++) = ((char *) &mask)[2]; +- *(result++) = ((char *) &mask)[3]; +- } +- +- /* add the payload */ +- if (0 != reason_code) +- { +- /* close reason code */ +- uint16_t reason_code_nb = MHD_htons (reason_code); +- MHD_websocket_copy_payload (result, +- (const char *) &reason_code_nb, +- 2, +- mask, +- 0); +- result += 2; +- +- /* custom reason payload */ +- if (0 != reason_utf8_len) +- { +- MHD_websocket_copy_payload (result, +- reason_utf8, +- reason_utf8_len, +- mask, +- 2); +- } +- } +- +- return MHD_WEBSOCKET_STATUS_OK; +-} +- +- +-/** +- * Returns the 0x80 prefix for masked data, 0x00 otherwise +- */ +-static char +-MHD_websocket_encode_is_masked (struct MHD_WebSocketStream *ws) +-{ +- return (ws->flags & MHD_WEBSOCKET_FLAG_MASK_SERVERCLIENT) == +- MHD_WEBSOCKET_FLAG_CLIENT ? 0x80 : 0x00; +-} +- +- +-/** +- * Calculates the size of the overhead in bytes +- */ +-static char +-MHD_websocket_encode_overhead_size (struct MHD_WebSocketStream *ws, +- size_t payload_len) +-{ +- return 2 + (MHD_websocket_encode_is_masked (ws) != 0 ? 4 : 0) + (125 < +- payload_len ? +- (65535 < +- payload_len +- ? 8 : 2) : 0); +-} +- +- +-/** +- * Copies the payload to the destination (using mask) +- */ +-static void +-MHD_websocket_copy_payload (char *dst, +- const char *src, +- size_t len, +- uint32_t mask, +- unsigned long mask_offset) +-{ +- if (0 != len) +- { +- if (0 == mask) +- { +- /* when the mask is zero, we can just copy the data */ +- memcpy (dst, src, len); +- } +- else +- { +- /* mask is used */ +- char mask_[4]; +- *((uint32_t *) mask_) = mask; +- for (size_t i = 0; i < len; ++i) +- { +- dst[i] = src[i] ^ mask_[(i + mask_offset) & 3]; +- } +- } +- } +-} +- +- +-/** +- * Checks a UTF-8 sequence +- */ +-static int +-MHD_websocket_check_utf8 (const char *buf, +- size_t buf_len, +- int *utf8_step, +- size_t *buf_offset) +-{ +- int utf8_step_ = (NULL != utf8_step) ? *utf8_step : +- MHD_WEBSOCKET_UTF8STEP_NORMAL; +- +- for (size_t i = 0; i < buf_len; ++i) +- { +- unsigned char character = (unsigned char) buf[i]; +- switch (utf8_step_) +- { +- case MHD_WEBSOCKET_UTF8STEP_NORMAL: +- if ((0x00 <= character) && (0x7F >= character)) +- { +- /* RFC 3629 4: single byte UTF-8 sequence */ +- /* (nothing to do here) */ +- } +- else if ((0xC2 <= character) && (0xDF >= character)) +- { +- /* RFC 3629 4: two byte UTF-8 sequence */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1; +- } +- else if (0xE0 == character) +- { +- /* RFC 3629 4: three byte UTF-8 sequence, but the second byte must be 0xA0-0xBF */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL1_1OF2; +- } +- else if (0xED == character) +- { +- /* RFC 3629 4: three byte UTF-8 sequence, but the second byte must be 0x80-0x9F */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2; +- } +- else if (((0xE1 <= character) && (0xEC >= character)) || +- ((0xEE <= character) && (0xEF >= character)) ) +- { +- /* RFC 3629 4: three byte UTF-8 sequence, both tail bytes must be 0x80-0xBF */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2; +- } +- else if (0xF0 == character) +- { +- /* RFC 3629 4: four byte UTF-8 sequence, but the second byte must be 0x90-0xBF */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL1_1OF3; +- } +- else if (0xF4 == character) +- { +- /* RFC 3629 4: four byte UTF-8 sequence, but the second byte must be 0x80-0x8F */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL2_1OF3; +- } +- else if ((0xF1 <= character) && (0xF3 >= character)) +- { +- /* RFC 3629 4: four byte UTF-8 sequence, all three tail bytes must be 0x80-0xBF */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_1OF3; +- } +- else +- { +- /* RFC 3629 4: Invalid UTF-8 byte */ +- if (NULL != buf_offset) +- *buf_offset = i; +- return MHD_WebSocket_UTF8Result_Invalid; +- } +- break; +- +- case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL1_1OF2: +- if ((0xA0 <= character) && (0xBF >= character)) +- { +- /* RFC 3629 4: Second byte of three byte UTF-8 sequence */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2; +- } +- else +- { +- /* RFC 3629 4: Invalid UTF-8 byte */ +- if (NULL != buf_offset) +- *buf_offset = i; +- return MHD_WebSocket_UTF8Result_Invalid; +- } +- break; +- +- case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2: +- if ((0x80 <= character) && (0x9F >= character)) +- { +- /* RFC 3629 4: Second byte of three byte UTF-8 sequence */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2; +- } +- else +- { +- /* RFC 3629 4: Invalid UTF-8 byte */ +- if (NULL != buf_offset) +- *buf_offset = i; +- return MHD_WebSocket_UTF8Result_Invalid; +- } +- break; +- +- case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2: +- if ((0x80 <= character) && (0xBF >= character)) +- { +- /* RFC 3629 4: Second byte of three byte UTF-8 sequence */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2; +- } +- else +- { +- /* RFC 3629 4: Invalid UTF-8 byte */ +- if (NULL != buf_offset) +- *buf_offset = i; +- return MHD_WebSocket_UTF8Result_Invalid; +- } +- break; +- +- case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL1_1OF3: +- if ((0x90 <= character) && (0xBF >= character)) +- { +- /* RFC 3629 4: Second byte of four byte UTF-8 sequence */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3; +- } +- else +- { +- /* RFC 3629 4: Invalid UTF-8 byte */ +- if (NULL != buf_offset) +- *buf_offset = i; +- return MHD_WebSocket_UTF8Result_Invalid; +- } +- break; +- +- case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL2_1OF3: +- if ((0x80 <= character) && (0x8F >= character)) +- { +- /* RFC 3629 4: Second byte of four byte UTF-8 sequence */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3; +- } +- else +- { +- /* RFC 3629 4: Invalid UTF-8 byte */ +- if (NULL != buf_offset) +- *buf_offset = i; +- return MHD_WebSocket_UTF8Result_Invalid; +- } +- break; +- +- case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_1OF3: +- if ((0x80 <= character) && (0xBF >= character)) +- { +- /* RFC 3629 4: Second byte of four byte UTF-8 sequence */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3; +- } +- else +- { +- /* RFC 3629 4: Invalid UTF-8 byte */ +- if (NULL != buf_offset) +- *buf_offset = i; +- return MHD_WebSocket_UTF8Result_Invalid; +- } +- break; +- +- case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3: +- if ((0x80 <= character) && (0xBF >= character)) +- { +- /* RFC 3629 4: Third byte of four byte UTF-8 sequence */ +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_3OF3; +- } +- else +- { +- /* RFC 3629 4: Invalid UTF-8 byte */ +- if (NULL != buf_offset) +- *buf_offset = i; +- return MHD_WebSocket_UTF8Result_Invalid; +- } +- break; +- +- /* RFC 3629 4: Second byte of two byte UTF-8 sequence */ +- case MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1: +- /* RFC 3629 4: Third byte of three byte UTF-8 sequence */ +- case MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2: +- /* RFC 3629 4: Fourth byte of four byte UTF-8 sequence */ +- case MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_3OF3: +- if ((0x80 <= character) && (0xBF >= character)) +- { +- utf8_step_ = MHD_WEBSOCKET_UTF8STEP_NORMAL; +- } +- else +- { +- /* RFC 3629 4: Invalid UTF-8 byte */ +- if (NULL != buf_offset) +- *buf_offset = i; +- return MHD_WebSocket_UTF8Result_Invalid; +- } +- break; +- +- default: +- /* Invalid last step...? */ +- if (NULL != buf_offset) +- *buf_offset = i; +- return MHD_WebSocket_UTF8Result_Invalid; +- } +- } +- +- /* return values */ +- if (NULL != utf8_step) +- *utf8_step = utf8_step_; +- if (NULL != buf_offset) +- *buf_offset = buf_len; +- if (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step_) +- { +- return MHD_WebSocket_UTF8Result_Incomplete; +- } +- return MHD_WebSocket_UTF8Result_Valid; +-} +- +- +-/** +- * Generates a mask for masking by calling +- * a random number generator. +- */ +-static uint32_t +-MHD_websocket_generate_mask (struct MHD_WebSocketStream *ws) +-{ +- unsigned char mask_[4]; +- if (NULL != ws->rng) +- { +- size_t offset = 0; +- while (offset < 4) +- { +- size_t encoded = ws->rng (ws->cls_rng, +- mask_ + offset, +- 4 - offset); +- offset += encoded; +- } +- } +- else +- { +- /* this case should never happen */ +- mask_ [0] = 0; +- mask_ [1] = 0; +- mask_ [2] = 0; +- mask_ [3] = 0; +- } +- +- return *((uint32_t *) mask_); +-} +- +- +-/** +- * Calls the malloc function associated with the websocket steam +- */ +-_MHD_EXTERN void * +-MHD_websocket_malloc (struct MHD_WebSocketStream *ws, +- size_t buf_len) +-{ +- if (NULL == ws) +- { +- return NULL; +- } +- +- return ws->malloc (buf_len); +-} +- +- +-/** +- * Calls the realloc function associated with the websocket steam +- */ +-_MHD_EXTERN void * +-MHD_websocket_realloc (struct MHD_WebSocketStream *ws, +- void *buf, +- size_t new_buf_len) +-{ +- if (NULL == ws) +- { +- return NULL; +- } +- +- return ws->realloc (buf, new_buf_len); +-} +- +- +-/** +- * Calls the free function associated with the websocket steam +- */ +-_MHD_EXTERN int +-MHD_websocket_free (struct MHD_WebSocketStream *ws, +- void *buf) +-{ +- if (NULL == ws) +- { +- return MHD_WEBSOCKET_STATUS_PARAMETER_ERROR; +- } +- +- ws->free (buf); +- +- return MHD_WEBSOCKET_STATUS_OK; +-} +- +- +-/** +- * Converts a 16 bit value into network byte order (MSB first) +- * in dependence of the host system +- */ +-static uint16_t +-MHD_htons (uint16_t value) +-{ +- uint16_t endian = 0x0001; +- +- if (((char *) &endian)[0] == 0x01) +- { +- /* least significant byte first */ +- ((char *) &endian)[0] = ((char *) &value)[1]; +- ((char *) &endian)[1] = ((char *) &value)[0]; +- return endian; +- } +- else +- { +- /* most significant byte first */ +- return value; +- } +-} +- +- +-/** +- * Converts a 64 bit value into network byte order (MSB first) +- * in dependence of the host system +- */ +-static uint64_t +-MHD_htonll (uint64_t value) +-{ +- uint64_t endian = 0x0000000000000001; +- +- if (((char *) &endian)[0] == 0x01) +- { +- /* least significant byte first */ +- ((char *) &endian)[0] = ((char *) &value)[7]; +- ((char *) &endian)[1] = ((char *) &value)[6]; +- ((char *) &endian)[2] = ((char *) &value)[5]; +- ((char *) &endian)[3] = ((char *) &value)[4]; +- ((char *) &endian)[4] = ((char *) &value)[3]; +- ((char *) &endian)[5] = ((char *) &value)[2]; +- ((char *) &endian)[6] = ((char *) &value)[1]; +- ((char *) &endian)[7] = ((char *) &value)[0]; +- return endian; +- } +- else +- { +- /* most significant byte first */ +- return value; +- } +-} +diff --git a/src/microhttpd_ws/sha1.c b/src/microhttpd_ws/sha1.c +deleted file mode 100644 +index 1e9da5c..0000000 +--- a/src/microhttpd_ws/sha1.c ++++ /dev/null +@@ -1,378 +0,0 @@ +-/* +- This file is part of libmicrohttpd +- Copyright (C) 2019-2021 Karlson2k (Evgeny Grin) +- +- libmicrohttpd is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- This library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with this library. +- If not, see . +-*/ +- +-/** +- * @file microhttpd/sha1.c +- * @brief Calculation of SHA-1 digest as defined in FIPS PUB 180-4 (2015) +- * @author Karlson2k (Evgeny Grin) +- */ +- +-#include "sha1.h" +- +-#include +-#ifdef HAVE_MEMORY_H +-#include +-#endif /* HAVE_MEMORY_H */ +-#include "mhd_bithelpers.h" +-#include "mhd_assert.h" +- +-/** +- * Initialise structure for SHA-1 calculation. +- * +- * @param ctx_ must be a `struct sha1_ctx *` +- */ +-void +-MHD_SHA1_init (void *ctx_) +-{ +- struct sha1_ctx *const ctx = ctx_; +- /* Initial hash values, see FIPS PUB 180-4 paragraph 5.3.1 */ +- /* Just some "magic" numbers defined by standard */ +- ctx->H[0] = UINT32_C (0x67452301); +- ctx->H[1] = UINT32_C (0xefcdab89); +- ctx->H[2] = UINT32_C (0x98badcfe); +- ctx->H[3] = UINT32_C (0x10325476); +- ctx->H[4] = UINT32_C (0xc3d2e1f0); +- +- /* Initialise number of bytes. */ +- ctx->count = 0; +-} +- +- +-/** +- * Base of SHA-1 transformation. +- * Gets full 512 bits / 64 bytes block of data and updates hash values; +- * @param H hash values +- * @param data data, must be exactly 64 bytes long +- */ +-static void +-sha1_transform (uint32_t H[_SHA1_DIGEST_LENGTH], +- const uint8_t data[SHA1_BLOCK_SIZE]) +-{ +- /* Working variables, +- see FIPS PUB 180-4 paragraph 6.1.3 */ +- uint32_t a = H[0]; +- uint32_t b = H[1]; +- uint32_t c = H[2]; +- uint32_t d = H[3]; +- uint32_t e = H[4]; +- +- /* Data buffer, used as cyclic buffer. +- See FIPS PUB 180-4 paragraphs 5.2.1, 6.1.3 */ +- uint32_t W[16]; +- +- /* 'Ch' and 'Maj' macro functions are defined with +- widely-used optimization. +- See FIPS PUB 180-4 formulae 4.1. */ +-#define Ch(x,y,z) ( (z) ^ ((x) & ((y) ^ (z))) ) +-#define Maj(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) ) +- /* Unoptimized (original) versions: */ +-/* #define Ch(x,y,z) ( ( (x) & (y) ) ^ ( ~(x) & (z) ) ) */ +-/* #define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) ) */ +-#define Par(x,y,z) ( (x) ^ (y) ^ (z) ) +- +- /* Single step of SHA-1 computation, +- see FIPS PUB 180-4 paragraph 6.1.3 step 3. +- * Note: instead of reassigning all working variables on each step, +- variables are rotated for each step: +- SHA1STEP32 (a, b, c, d, e, func, K00, W[0]); +- SHA1STEP32 (e, a, b, c, d, func, K00, W[1]); +- so current 'vC' will be used as 'vD' on the next step, +- current 'vE' will be used as 'vA' on the next step. +- * Note: 'wt' must be used exactly one time in this macro as it change other data as well +- every time when used. */ +- +-#define SHA1STEP32(vA,vB,vC,vD,vE,ft,kt,wt) do { \ +- (vE) += _MHD_ROTL32 ((vA), 5) + ft ((vB), (vC), (vD)) + (kt) + (wt); \ +- (vB) = _MHD_ROTL32 ((vB), 30); } while (0) +- +- /* Get value of W(t) from input data buffer, +- See FIPS PUB 180-4 paragraph 6.1.3. +- Input data must be read in big-endian bytes order, +- see FIPS PUB 180-4 paragraph 3.1.2. */ +-#define GET_W_FROM_DATA(buf,t) \ +- _MHD_GET_32BIT_BE (((const uint8_t*) (buf)) + (t) * SHA1_BYTES_IN_WORD) +- +-#ifndef _MHD_GET_32BIT_BE_UNALIGNED +- if (0 != (((uintptr_t) data) % _MHD_UINT32_ALIGN)) +- { +- /* Copy the unaligned input data to the aligned buffer */ +- memcpy (W, data, SHA1_BLOCK_SIZE); +- /* The W[] buffer itself will be used as the source of the data, +- * but data will be reloaded in correct bytes order during +- * the next steps */ +- data = (uint8_t *) W; +- } +-#endif /* _MHD_GET_32BIT_BE_UNALIGNED */ +- +-/* SHA-1 values of Kt for t=0..19, see FIPS PUB 180-4 paragraph 4.2.1. */ +-#define K00 UINT32_C(0x5a827999) +-/* SHA-1 values of Kt for t=20..39, see FIPS PUB 180-4 paragraph 4.2.1.*/ +-#define K20 UINT32_C(0x6ed9eba1) +-/* SHA-1 values of Kt for t=40..59, see FIPS PUB 180-4 paragraph 4.2.1.*/ +-#define K40 UINT32_C(0x8f1bbcdc) +-/* SHA-1 values of Kt for t=60..79, see FIPS PUB 180-4 paragraph 4.2.1.*/ +-#define K60 UINT32_C(0xca62c1d6) +- +- /* During first 16 steps, before making any calculations on each step, +- the W element is read from input data buffer as big-endian value and +- stored in array of W elements. */ +- /* Note: instead of using K constants as array, all K values are specified +- individually for each step. */ +- SHA1STEP32 (a, b, c, d, e, Ch, K00, W[0] = GET_W_FROM_DATA (data, 0)); +- SHA1STEP32 (e, a, b, c, d, Ch, K00, W[1] = GET_W_FROM_DATA (data, 1)); +- SHA1STEP32 (d, e, a, b, c, Ch, K00, W[2] = GET_W_FROM_DATA (data, 2)); +- SHA1STEP32 (c, d, e, a, b, Ch, K00, W[3] = GET_W_FROM_DATA (data, 3)); +- SHA1STEP32 (b, c, d, e, a, Ch, K00, W[4] = GET_W_FROM_DATA (data, 4)); +- SHA1STEP32 (a, b, c, d, e, Ch, K00, W[5] = GET_W_FROM_DATA (data, 5)); +- SHA1STEP32 (e, a, b, c, d, Ch, K00, W[6] = GET_W_FROM_DATA (data, 6)); +- SHA1STEP32 (d, e, a, b, c, Ch, K00, W[7] = GET_W_FROM_DATA (data, 7)); +- SHA1STEP32 (c, d, e, a, b, Ch, K00, W[8] = GET_W_FROM_DATA (data, 8)); +- SHA1STEP32 (b, c, d, e, a, Ch, K00, W[9] = GET_W_FROM_DATA (data, 9)); +- SHA1STEP32 (a, b, c, d, e, Ch, K00, W[10] = GET_W_FROM_DATA (data, 10)); +- SHA1STEP32 (e, a, b, c, d, Ch, K00, W[11] = GET_W_FROM_DATA (data, 11)); +- SHA1STEP32 (d, e, a, b, c, Ch, K00, W[12] = GET_W_FROM_DATA (data, 12)); +- SHA1STEP32 (c, d, e, a, b, Ch, K00, W[13] = GET_W_FROM_DATA (data, 13)); +- SHA1STEP32 (b, c, d, e, a, Ch, K00, W[14] = GET_W_FROM_DATA (data, 14)); +- SHA1STEP32 (a, b, c, d, e, Ch, K00, W[15] = GET_W_FROM_DATA (data, 15)); +- +- /* 'W' generation and assignment for 16 <= t <= 79. +- See FIPS PUB 180-4 paragraph 6.1.3. +- As only last 16 'W' are used in calculations, it is possible to +- use 16 elements array of W as cyclic buffer. */ +-#define Wgen(w,t) _MHD_ROTL32((w)[(t + 13) & 0xf] ^ (w)[(t + 8) & 0xf] \ +- ^ (w)[(t + 2) & 0xf] ^ (w)[t & 0xf], 1) +- +- /* During last 60 steps, before making any calculations on each step, +- W element is generated from W elements of cyclic buffer and generated value +- stored back in cyclic buffer. */ +- /* Note: instead of using K constants as array, all K values are specified +- individually for each step, see FIPS PUB 180-4 paragraph 4.2.1. */ +- SHA1STEP32 (e, a, b, c, d, Ch, K00, W[16 & 0xf] = Wgen (W, 16)); +- SHA1STEP32 (d, e, a, b, c, Ch, K00, W[17 & 0xf] = Wgen (W, 17)); +- SHA1STEP32 (c, d, e, a, b, Ch, K00, W[18 & 0xf] = Wgen (W, 18)); +- SHA1STEP32 (b, c, d, e, a, Ch, K00, W[19 & 0xf] = Wgen (W, 19)); +- SHA1STEP32 (a, b, c, d, e, Par, K20, W[20 & 0xf] = Wgen (W, 20)); +- SHA1STEP32 (e, a, b, c, d, Par, K20, W[21 & 0xf] = Wgen (W, 21)); +- SHA1STEP32 (d, e, a, b, c, Par, K20, W[22 & 0xf] = Wgen (W, 22)); +- SHA1STEP32 (c, d, e, a, b, Par, K20, W[23 & 0xf] = Wgen (W, 23)); +- SHA1STEP32 (b, c, d, e, a, Par, K20, W[24 & 0xf] = Wgen (W, 24)); +- SHA1STEP32 (a, b, c, d, e, Par, K20, W[25 & 0xf] = Wgen (W, 25)); +- SHA1STEP32 (e, a, b, c, d, Par, K20, W[26 & 0xf] = Wgen (W, 26)); +- SHA1STEP32 (d, e, a, b, c, Par, K20, W[27 & 0xf] = Wgen (W, 27)); +- SHA1STEP32 (c, d, e, a, b, Par, K20, W[28 & 0xf] = Wgen (W, 28)); +- SHA1STEP32 (b, c, d, e, a, Par, K20, W[29 & 0xf] = Wgen (W, 29)); +- SHA1STEP32 (a, b, c, d, e, Par, K20, W[30 & 0xf] = Wgen (W, 30)); +- SHA1STEP32 (e, a, b, c, d, Par, K20, W[31 & 0xf] = Wgen (W, 31)); +- SHA1STEP32 (d, e, a, b, c, Par, K20, W[32 & 0xf] = Wgen (W, 32)); +- SHA1STEP32 (c, d, e, a, b, Par, K20, W[33 & 0xf] = Wgen (W, 33)); +- SHA1STEP32 (b, c, d, e, a, Par, K20, W[34 & 0xf] = Wgen (W, 34)); +- SHA1STEP32 (a, b, c, d, e, Par, K20, W[35 & 0xf] = Wgen (W, 35)); +- SHA1STEP32 (e, a, b, c, d, Par, K20, W[36 & 0xf] = Wgen (W, 36)); +- SHA1STEP32 (d, e, a, b, c, Par, K20, W[37 & 0xf] = Wgen (W, 37)); +- SHA1STEP32 (c, d, e, a, b, Par, K20, W[38 & 0xf] = Wgen (W, 38)); +- SHA1STEP32 (b, c, d, e, a, Par, K20, W[39 & 0xf] = Wgen (W, 39)); +- SHA1STEP32 (a, b, c, d, e, Maj, K40, W[40 & 0xf] = Wgen (W, 40)); +- SHA1STEP32 (e, a, b, c, d, Maj, K40, W[41 & 0xf] = Wgen (W, 41)); +- SHA1STEP32 (d, e, a, b, c, Maj, K40, W[42 & 0xf] = Wgen (W, 42)); +- SHA1STEP32 (c, d, e, a, b, Maj, K40, W[43 & 0xf] = Wgen (W, 43)); +- SHA1STEP32 (b, c, d, e, a, Maj, K40, W[44 & 0xf] = Wgen (W, 44)); +- SHA1STEP32 (a, b, c, d, e, Maj, K40, W[45 & 0xf] = Wgen (W, 45)); +- SHA1STEP32 (e, a, b, c, d, Maj, K40, W[46 & 0xf] = Wgen (W, 46)); +- SHA1STEP32 (d, e, a, b, c, Maj, K40, W[47 & 0xf] = Wgen (W, 47)); +- SHA1STEP32 (c, d, e, a, b, Maj, K40, W[48 & 0xf] = Wgen (W, 48)); +- SHA1STEP32 (b, c, d, e, a, Maj, K40, W[49 & 0xf] = Wgen (W, 49)); +- SHA1STEP32 (a, b, c, d, e, Maj, K40, W[50 & 0xf] = Wgen (W, 50)); +- SHA1STEP32 (e, a, b, c, d, Maj, K40, W[51 & 0xf] = Wgen (W, 51)); +- SHA1STEP32 (d, e, a, b, c, Maj, K40, W[52 & 0xf] = Wgen (W, 52)); +- SHA1STEP32 (c, d, e, a, b, Maj, K40, W[53 & 0xf] = Wgen (W, 53)); +- SHA1STEP32 (b, c, d, e, a, Maj, K40, W[54 & 0xf] = Wgen (W, 54)); +- SHA1STEP32 (a, b, c, d, e, Maj, K40, W[55 & 0xf] = Wgen (W, 55)); +- SHA1STEP32 (e, a, b, c, d, Maj, K40, W[56 & 0xf] = Wgen (W, 56)); +- SHA1STEP32 (d, e, a, b, c, Maj, K40, W[57 & 0xf] = Wgen (W, 57)); +- SHA1STEP32 (c, d, e, a, b, Maj, K40, W[58 & 0xf] = Wgen (W, 58)); +- SHA1STEP32 (b, c, d, e, a, Maj, K40, W[59 & 0xf] = Wgen (W, 59)); +- SHA1STEP32 (a, b, c, d, e, Par, K60, W[60 & 0xf] = Wgen (W, 60)); +- SHA1STEP32 (e, a, b, c, d, Par, K60, W[61 & 0xf] = Wgen (W, 61)); +- SHA1STEP32 (d, e, a, b, c, Par, K60, W[62 & 0xf] = Wgen (W, 62)); +- SHA1STEP32 (c, d, e, a, b, Par, K60, W[63 & 0xf] = Wgen (W, 63)); +- SHA1STEP32 (b, c, d, e, a, Par, K60, W[64 & 0xf] = Wgen (W, 64)); +- SHA1STEP32 (a, b, c, d, e, Par, K60, W[65 & 0xf] = Wgen (W, 65)); +- SHA1STEP32 (e, a, b, c, d, Par, K60, W[66 & 0xf] = Wgen (W, 66)); +- SHA1STEP32 (d, e, a, b, c, Par, K60, W[67 & 0xf] = Wgen (W, 67)); +- SHA1STEP32 (c, d, e, a, b, Par, K60, W[68 & 0xf] = Wgen (W, 68)); +- SHA1STEP32 (b, c, d, e, a, Par, K60, W[69 & 0xf] = Wgen (W, 69)); +- SHA1STEP32 (a, b, c, d, e, Par, K60, W[70 & 0xf] = Wgen (W, 70)); +- SHA1STEP32 (e, a, b, c, d, Par, K60, W[71 & 0xf] = Wgen (W, 71)); +- SHA1STEP32 (d, e, a, b, c, Par, K60, W[72 & 0xf] = Wgen (W, 72)); +- SHA1STEP32 (c, d, e, a, b, Par, K60, W[73 & 0xf] = Wgen (W, 73)); +- SHA1STEP32 (b, c, d, e, a, Par, K60, W[74 & 0xf] = Wgen (W, 74)); +- SHA1STEP32 (a, b, c, d, e, Par, K60, W[75 & 0xf] = Wgen (W, 75)); +- SHA1STEP32 (e, a, b, c, d, Par, K60, W[76 & 0xf] = Wgen (W, 76)); +- SHA1STEP32 (d, e, a, b, c, Par, K60, W[77 & 0xf] = Wgen (W, 77)); +- SHA1STEP32 (c, d, e, a, b, Par, K60, W[78 & 0xf] = Wgen (W, 78)); +- SHA1STEP32 (b, c, d, e, a, Par, K60, W[79 & 0xf] = Wgen (W, 79)); +- +- /* Compute intermediate hash. +- See FIPS PUB 180-4 paragraph 6.1.3 step 4. */ +- H[0] += a; +- H[1] += b; +- H[2] += c; +- H[3] += d; +- H[4] += e; +-} +- +- +-/** +- * Process portion of bytes. +- * +- * @param ctx_ must be a `struct sha1_ctx *` +- * @param data bytes to add to hash +- * @param length number of bytes in @a data +- */ +-void +-MHD_SHA1_update (void *ctx_, +- const uint8_t *data, +- size_t length) +-{ +- struct sha1_ctx *const ctx = ctx_; +- unsigned bytes_have; /**< Number of bytes in buffer */ +- +- mhd_assert ((data != NULL) || (length == 0)); +- +- if (0 == length) +- return; /* Do nothing */ +- +- /* Note: (count & (SHA1_BLOCK_SIZE-1)) +- equal (count % SHA1_BLOCK_SIZE) for this block size. */ +- bytes_have = (unsigned) (ctx->count & (SHA1_BLOCK_SIZE - 1)); +- ctx->count += length; +- +- if (0 != bytes_have) +- { +- unsigned bytes_left = SHA1_BLOCK_SIZE - bytes_have; +- if (length >= bytes_left) +- { /* Combine new data with the data in the buffer and +- process the full block. */ +- memcpy (ctx->buffer + bytes_have, +- data, +- bytes_left); +- data += bytes_left; +- length -= bytes_left; +- sha1_transform (ctx->H, ctx->buffer); +- bytes_have = 0; +- } +- } +- +- while (SHA1_BLOCK_SIZE <= length) +- { /* Process any full blocks of new data directly, +- without copying to the buffer. */ +- sha1_transform (ctx->H, data); +- data += SHA1_BLOCK_SIZE; +- length -= SHA1_BLOCK_SIZE; +- } +- +- if (0 != length) +- { /* Copy incomplete block of new data (if any) +- to the buffer. */ +- memcpy (ctx->buffer + bytes_have, data, length); +- } +-} +- +- +-/** +- * Size of "length" padding addition in bytes. +- * See FIPS PUB 180-4 paragraph 5.1.1. +- */ +-#define SHA1_SIZE_OF_LEN_ADD (64 / 8) +- +-/** +- * Finalise SHA-1 calculation, return digest. +- * +- * @param ctx_ must be a `struct sha1_ctx *` +- * @param[out] digest set to the hash, must be #SHA1_DIGEST_SIZE bytes +- */ +-void +-MHD_SHA1_finish (void *ctx_, +- uint8_t digest[SHA1_DIGEST_SIZE]) +-{ +- struct sha1_ctx *const ctx = ctx_; +- uint64_t num_bits; /**< Number of processed bits */ +- unsigned bytes_have; /**< Number of bytes in buffer */ +- +- num_bits = ctx->count << 3; +- /* Note: (count & (SHA1_BLOCK_SIZE-1)) +- equals (count % SHA1_BLOCK_SIZE) for this block size. */ +- bytes_have = (unsigned) (ctx->count & (SHA1_BLOCK_SIZE - 1)); +- +- /* Input data must be padded with bit "1" and with length of data in bits. +- See FIPS PUB 180-4 paragraph 5.1.1. */ +- /* Data is always processed in form of bytes (not by individual bits), +- therefore position of first padding bit in byte is always predefined (0x80). */ +- /* Buffer always have space at least for one byte (as full buffers are +- processed immediately). */ +- ctx->buffer[bytes_have++] = 0x80; +- +- if (SHA1_BLOCK_SIZE - bytes_have < SHA1_SIZE_OF_LEN_ADD) +- { /* No space in current block to put total length of message. +- Pad current block with zeros and process it. */ +- if (SHA1_BLOCK_SIZE > bytes_have) +- memset (ctx->buffer + bytes_have, 0, SHA1_BLOCK_SIZE - bytes_have); +- /* Process full block. */ +- sha1_transform (ctx->H, ctx->buffer); +- /* Start new block. */ +- bytes_have = 0; +- } +- +- /* Pad the rest of the buffer with zeros. */ +- memset (ctx->buffer + bytes_have, 0, +- SHA1_BLOCK_SIZE - SHA1_SIZE_OF_LEN_ADD - bytes_have); +- /* Put the number of bits in the processed message as a big-endian value. */ +- _MHD_PUT_64BIT_BE_SAFE (ctx->buffer + SHA1_BLOCK_SIZE - SHA1_SIZE_OF_LEN_ADD, +- num_bits); +- /* Process the full final block. */ +- sha1_transform (ctx->H, ctx->buffer); +- +- /* Put final hash/digest in BE mode */ +-#ifndef _MHD_PUT_32BIT_BE_UNALIGNED +- if (0 != ((uintptr_t) digest) % _MHD_UINT32_ALIGN) +- { +- uint32_t alig_dgst[_SHA1_DIGEST_LENGTH]; +- _MHD_PUT_32BIT_BE (alig_dgst + 0, ctx->H[0]); +- _MHD_PUT_32BIT_BE (alig_dgst + 1, ctx->H[1]); +- _MHD_PUT_32BIT_BE (alig_dgst + 2, ctx->H[2]); +- _MHD_PUT_32BIT_BE (alig_dgst + 3, ctx->H[3]); +- _MHD_PUT_32BIT_BE (alig_dgst + 4, ctx->H[4]); +- /* Copy result to unaligned destination address */ +- memcpy (digest, alig_dgst, SHA1_DIGEST_SIZE); +- } +- else +-#else /* _MHD_PUT_32BIT_BE_UNALIGNED */ +- if (1) +-#endif /* _MHD_PUT_32BIT_BE_UNALIGNED */ +- { +- _MHD_PUT_32BIT_BE (digest + 0 * SHA1_BYTES_IN_WORD, ctx->H[0]); +- _MHD_PUT_32BIT_BE (digest + 1 * SHA1_BYTES_IN_WORD, ctx->H[1]); +- _MHD_PUT_32BIT_BE (digest + 2 * SHA1_BYTES_IN_WORD, ctx->H[2]); +- _MHD_PUT_32BIT_BE (digest + 3 * SHA1_BYTES_IN_WORD, ctx->H[3]); +- _MHD_PUT_32BIT_BE (digest + 4 * SHA1_BYTES_IN_WORD, ctx->H[4]); +- } +- +- /* Erase potentially sensitive data. */ +- memset (ctx, 0, sizeof(struct sha1_ctx)); +-} +diff --git a/src/microhttpd_ws/sha1.h b/src/microhttpd_ws/sha1.h +deleted file mode 100644 +index 851a442..0000000 +--- a/src/microhttpd_ws/sha1.h ++++ /dev/null +@@ -1,110 +0,0 @@ +-/* +- This file is part of libmicrohttpd +- Copyright (C) 2019-2021 Karlson2k (Evgeny Grin) +- +- This library is free software; you can redistribute it and/or +- modify it under the terms of the GNU Lesser General Public +- License as published by the Free Software Foundation; either +- version 2.1 of the License, or (at your option) any later version. +- +- This library is distributed in the hope that it will be useful, +- but WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public +- License along with this library. +- If not, see . +-*/ +- +-/** +- * @file microhttpd/sha1.h +- * @brief Calculation of SHA-1 digest +- * @author Karlson2k (Evgeny Grin) +- */ +- +-#ifndef MHD_SHA1_H +-#define MHD_SHA1_H 1 +- +-#include "mhd_options.h" +-#include +-#ifdef HAVE_STDDEF_H +-#include /* for size_t */ +-#endif /* HAVE_STDDEF_H */ +- +-/** +- * SHA-1 digest is kept internally as 5 32-bit words. +- */ +-#define _SHA1_DIGEST_LENGTH 5 +- +-/** +- * Number of bits in single SHA-1 word +- */ +-#define SHA1_WORD_SIZE_BITS 32 +- +-/** +- * Number of bytes in single SHA-1 word +- */ +-#define SHA1_BYTES_IN_WORD (SHA1_WORD_SIZE_BITS / 8) +- +-/** +- * Size of SHA-1 digest in bytes +- */ +-#define SHA1_DIGEST_SIZE (_SHA1_DIGEST_LENGTH * SHA1_BYTES_IN_WORD) +- +-/** +- * Size of SHA-1 digest string in chars including termination NUL +- */ +-#define SHA1_DIGEST_STRING_SIZE ((SHA1_DIGEST_SIZE) * 2 + 1) +- +-/** +- * Size of single processing block in bits +- */ +-#define SHA1_BLOCK_SIZE_BITS 512 +- +-/** +- * Size of single processing block in bytes +- */ +-#define SHA1_BLOCK_SIZE (SHA1_BLOCK_SIZE_BITS / 8) +- +- +-struct sha1_ctx +-{ +- uint32_t H[_SHA1_DIGEST_LENGTH]; /**< Intermediate hash value / digest at end of calculation */ +- uint8_t buffer[SHA1_BLOCK_SIZE]; /**< SHA256 input data buffer */ +- uint64_t count; /**< number of bytes, mod 2^64 */ +-}; +- +-/** +- * Initialise structure for SHA-1 calculation. +- * +- * @param ctx must be a `struct sha1_ctx *` +- */ +-void +-MHD_SHA1_init (void *ctx_); +- +- +-/** +- * Process portion of bytes. +- * +- * @param ctx_ must be a `struct sha1_ctx *` +- * @param data bytes to add to hash +- * @param length number of bytes in @a data +- */ +-void +-MHD_SHA1_update (void *ctx_, +- const uint8_t *data, +- size_t length); +- +- +-/** +- * Finalise SHA-1 calculation, return digest. +- * +- * @param ctx_ must be a `struct sha1_ctx *` +- * @param[out] digest set to the hash, must be #SHA1_DIGEST_SIZE bytes +- */ +-void +-MHD_SHA1_finish (void *ctx_, +- uint8_t digest[SHA1_DIGEST_SIZE]); +- +-#endif /* MHD_SHA1_H */ +diff --git a/src/microhttpd_ws/test_websocket.c b/src/microhttpd_ws/test_websocket.c +deleted file mode 100644 +index 00fd8e0..0000000 +--- a/src/microhttpd_ws/test_websocket.c ++++ /dev/null +@@ -1,10105 +0,0 @@ +-/* +- This file is part of libmicrohttpd +- Copyright (C) 2021 David Gausmann +- +- libmicrohttpd is free software; you can redistribute it and/or modify +- it under the terms of the GNU General Public License as published +- by the Free Software Foundation; either version 3, or (at your +- option) any later version. +- +- libmicrohttpd is distributed in the hope that it will be useful, but +- WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- General Public License for more details. +- +- You should have received a copy of the GNU General Public License +- along with libmicrohttpd; see the file COPYING. If not, write to the +- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +- Boston, MA 02110-1301, USA. +-*/ +-/** +- * @file test_websocket.c +- * @brief Testcase for WebSocket decoding/encoding +- * @author David Gausmann +- */ +-#include "microhttpd.h" +-#include "microhttpd_ws.h" +-#include +-#include +-#include +-#include +-#include +- +-#if SIZE_MAX >= 0x100000000 +- #define ENABLE_64BIT_TESTS 1 +-#endif +- +-int disable_alloc = 0; +-size_t open_allocs = 0; +- +-/** +- * Custom `malloc()` function used for memory tests +- */ +-static void * +-test_malloc (size_t buf_len) +-{ +- if (0 != disable_alloc) +- return NULL; +- void *result = malloc (buf_len); +- if (NULL != result) +- ++open_allocs; +- return result; +-} +- +- +-/** +- * Custom `realloc()` function used for memory tests +- */ +-static void * +-test_realloc (void *buf, size_t buf_len) +-{ +- if (0 != disable_alloc) +- return NULL; +- void *result = realloc (buf, buf_len); +- if ((NULL != result) && (NULL == buf)) +- ++open_allocs; +- return result; +-} +- +- +-/** +- * Custom `free()` function used for memory tests +- */ +-static void +-test_free (void *buf) +-{ +- if (NULL != buf) +- --open_allocs; +- free (buf); +-} +- +- +-/** +- * Custom `rng()` function used for client mode tests +- */ +-static size_t +-test_rng (void *cls, void *buf, size_t buf_len) +-{ +- for (size_t i = 0; i < buf_len; ++i) +- { +- ((char *) buf) [i] = (char) (rand () % 0xFF); +- } +- +- return buf_len; +-} +- +- +-/** +- * Helper function which allocates a big amount of data +- */ +-static void +-allocate_length_test_data (char **buf1, +- char **buf2, +- size_t buf_len, +- const char *buf1_prefix, +- size_t buf1_prefix_len) +-{ +- if (NULL != *buf1) +- free (*buf1); +- if (NULL != *buf2) +- free (*buf2); +- *buf1 = (char *) malloc (buf_len + buf1_prefix_len); +- *buf2 = (char *) malloc (buf_len); +- if ((NULL == buf1) || (NULL == buf2)) +- return; +- memcpy (*buf1, +- buf1_prefix, +- buf1_prefix_len); +- for (size_t i = 0; i < buf_len; i += 64) +- { +- size_t bytes_to_copy = buf_len - i; +- if (64 < bytes_to_copy) +- bytes_to_copy = 64; +- memcpy (*buf1 + i + buf1_prefix_len, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-", +- bytes_to_copy); +- memcpy (*buf2 + i, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-", +- bytes_to_copy); +- } +-} +- +- +-/** +- * Helper function which performs a single decoder test +- */ +-static int +-test_decode_single (unsigned int test_line, +- int flags, size_t max_payload_size, size_t decode_count, +- size_t buf_step, +- const char *buf, size_t buf_len, +- const char *expected_payload, size_t expected_payload_len, +- int expected_return, int expected_valid, size_t +- expected_streambuf_read_len) +-{ +- struct MHD_WebSocketStream *ws = NULL; +- int ret = MHD_WEBSOCKET_STATUS_OK; +- +- /* initialize stream */ +- ret = MHD_websocket_stream_init2 (&ws, +- flags, +- max_payload_size, +- malloc, +- realloc, +- free, +- NULL, +- test_rng); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "Allocation failed for decode test in line %u.\n", +- (unsigned int) test_line); +- return 1; +- } +- +- /* perform decoding in a loop */ +- size_t streambuf_read_len = 0; +- size_t payload_len = 0; +- char *payload = NULL; +- for (size_t i = 0; i < decode_count; ++i) +- { +- size_t streambuf_read_len_ = 0; +- size_t bytes_to_take = buf_len - streambuf_read_len; +- if ((0 != buf_step) && (buf_step < bytes_to_take)) +- bytes_to_take = buf_step; +- ret = MHD_websocket_decode (ws, buf + streambuf_read_len, bytes_to_take, +- &streambuf_read_len_, &payload, &payload_len); +- streambuf_read_len += streambuf_read_len_; +- if (i + 1 < decode_count) +- { +- if (payload) +- { +- MHD_websocket_free (ws, payload); +- payload = NULL; +- payload_len = 0; +- } +- } +- } +- +- /* check the (last) result */ +- if (ret != expected_return) +- { +- fprintf (stderr, +- "Decode test failed in line %u: The return value should be %d, but is %d\n", +- (unsigned int) test_line, +- (int) expected_return, +- (int) ret); +- MHD_websocket_free (ws, payload); +- MHD_websocket_stream_free (ws); +- return 1; +- } +- if (payload_len != expected_payload_len) +- { +- fprintf (stderr, +- "Decode test failed in line %u: The payload_len should be %u, but is %u\n", +- (unsigned int) test_line, +- (unsigned int) expected_payload_len, +- (unsigned int) payload_len); +- MHD_websocket_free (ws, payload); +- MHD_websocket_stream_free (ws); +- return 1; +- } +- if (0 != payload_len) +- { +- if (NULL == payload) +- { +- fprintf (stderr, +- "Decode test failed in line %u: The payload is NULL\n", +- (unsigned int) test_line); +- MHD_websocket_free (ws, payload); +- MHD_websocket_stream_free (ws); +- return 1; +- } +- else if (NULL == expected_payload) +- { +- fprintf (stderr, +- "Decode test failed in line %u: The expected_payload is NULL (wrong test declaration)\n", +- (unsigned int) test_line); +- MHD_websocket_free (ws, payload); +- MHD_websocket_stream_free (ws); +- return 1; +- } +- else if (0 != memcmp (payload, expected_payload, payload_len)) +- { +- fprintf (stderr, +- "Decode test failed in line %u: The payload differs from the expected_payload\n", +- (unsigned int) test_line); +- MHD_websocket_free (ws, payload); +- MHD_websocket_stream_free (ws); +- return 1; +- } +- } +- else +- { +- if (NULL != payload) +- { +- fprintf (stderr, +- "Decode test failed in line %u: The payload is not NULL, but payload_len is 0\n", +- (unsigned int) test_line); +- MHD_websocket_free (ws, payload); +- MHD_websocket_stream_free (ws); +- return 1; +- } +- else if (NULL != expected_payload) +- { +- fprintf (stderr, +- "Decode test failed in line %u: The expected_payload is not NULL, but expected_payload_len is 0 (wrong test declaration)\n", +- (unsigned int) test_line); +- MHD_websocket_free (ws, payload); +- MHD_websocket_stream_free (ws); +- return 1; +- } +- } +- if (streambuf_read_len != expected_streambuf_read_len) +- { +- fprintf (stderr, +- "Decode test failed in line %u: The streambuf_read_len should be %u, but is %u\n", +- (unsigned int) test_line, +- (unsigned int) expected_streambuf_read_len, +- (unsigned int) streambuf_read_len); +- MHD_websocket_free (ws, payload); +- MHD_websocket_stream_free (ws); +- return 1; +- } +- ret = MHD_websocket_stream_is_valid (ws); +- if (ret != expected_valid) +- { +- fprintf (stderr, +- "Decode test failed in line %u: The stream validity should be %u, but is %u\n", +- (unsigned int) test_line, +- (int) expected_valid, +- (int) ret); +- MHD_websocket_free (ws, payload); +- MHD_websocket_stream_free (ws); +- return 1; +- } +- +- /* cleanup */ +- MHD_websocket_free (ws, payload); +- MHD_websocket_stream_free (ws); +- +- return 0; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_stream_init()` and +- * `MHD_websocket_stream_init2()` +- */ +-int +-test_inits () +-{ +- int failed = 0; +- struct MHD_WebSocketStream *ws; +- int ret; +- +- /* +- ------------------------------------------------------------------------------ +- All valid flags +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: all valid flags for init (only the even ones work) */ +- for (int i = 0; i < 7; ++i) +- { +- ws = NULL; +- ret = MHD_websocket_stream_init (&ws, +- i, +- 0); +- if (((0 == (i & MHD_WEBSOCKET_FLAG_CLIENT)) && +- ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws))) || +- ((0 != (i & MHD_WEBSOCKET_FLAG_CLIENT)) && +- ((MHD_WEBSOCKET_STATUS_OK == ret) || +- (NULL != ws)))) +- { +- fprintf (stderr, +- "Init test failed in line %u for flags %d.\n", +- (unsigned int) __LINE__, +- (int) i); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- } +- /* Regular test: all valid flags for init2 */ +- for (int i = 0; i < 7; ++i) +- { +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- i, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- test_rng); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for flags %d.\n", +- (unsigned int) __LINE__, +- (int) i); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- } +- /* Fail test: Invalid flags for init */ +- for (int i = 4; i < 32; ++i) +- { +- int flags = 1 << i; +- ws = NULL; +- ret = MHD_websocket_stream_init (&ws, +- flags, +- 0); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for invalid flags %d.\n", +- (unsigned int) __LINE__, +- (int) flags); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- } +- /* Fail test: Invalid flag for init2 */ +- for (int i = 4; i < 32; ++i) +- { +- int flags = 1 << i; +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- flags, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for invalid flags %d.\n", +- (unsigned int) __LINE__, +- (int) flags); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- } +- +- /* +- ------------------------------------------------------------------------------ +- max_payload_size +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: max_payload_size = 0 for init */ +- ws = NULL; +- ret = MHD_websocket_stream_init (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for max_payload_size 0.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Regular test: max_payload_size = 0 for init2 */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for max_payload_size 0.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Edge test (success): max_payload_size = 1 for init */ +- ws = NULL; +- ret = MHD_websocket_stream_init (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 1); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for max_payload_size 1.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Edge test (success): max_payload_size = 1 for init2 */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 1, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for max_payload_size 1.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Regular test: max_payload_size = 1000 for init */ +- ws = NULL; +- ret = MHD_websocket_stream_init (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 1000); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for max_payload_size 1000.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Regular test: max_payload_size = 1000 for init2 */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 1000, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for max_payload_size 1000.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +-#ifdef ENABLE_64BIT_TESTS +- /* Edge test (success): max_payload_size = 0x7FFFFFFFFFFFFFFF for init */ +- ws = NULL; +- ret = MHD_websocket_stream_init (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- (uint64_t) 0x7FFFFFFFFFFFFFFF); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for max_payload_size 0x7FFFFFFFFFFFFFFF.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Edge test (success): max_payload_size = 0x7FFFFFFFFFFFFFFF for init2 */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- (uint64_t) 0x7FFFFFFFFFFFFFFF, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for max_payload_size 0x7FFFFFFFFFFFFFFF.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Edge test (fail): max_payload_size = 0x8000000000000000 for init */ +- ws = NULL; +- ret = MHD_websocket_stream_init (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- (uint64_t) 0x8000000000000000); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for max_payload_size 0x8000000000000000.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Edge test (fail): max_payload_size = 0x8000000000000000 for init2 */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- (uint64_t) 0x8000000000000000, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u for max_payload_size 0x8000000000000000.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +-#endif +- +- /* +- ------------------------------------------------------------------------------ +- Missing parameters +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: websocket stream variable missing for init */ +- ws = NULL; +- ret = MHD_websocket_stream_init (NULL, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Fail test: websocket stream variable missing for init2 */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (NULL, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Fail test: malloc missing for init2 */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- NULL, +- test_realloc, +- test_free, +- NULL, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Fail test: realloc missing for init2 */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- NULL, +- test_free, +- NULL, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Fail test: free missing for init2 */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- NULL, +- NULL, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Regular test: rng given for server mode (will be ignored) */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- test_rng); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Regular test: cls_rng given for server mode (will be ignored) */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- (void *) 12345, +- test_rng); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Regular test: rng given for client mode */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- test_rng); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL == ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- /* Fail test: rng not given for client mode */ +- ws = NULL; +- ret = MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != ws) ) +- { +- fprintf (stderr, +- "Init test failed in line %u %u.\n", +- (unsigned int) __LINE__, ret); +- ++failed; +- } +- if (NULL != ws) +- { +- MHD_websocket_stream_free (ws); +- ws = NULL; +- } +- +- return failed != 0 ? 0x01 : 0x00; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_create_accept_header()` +- */ +-int +-test_accept () +-{ +- int failed = 0; +- char accept_key[29]; +- int ret; +- +- /* +- ------------------------------------------------------------------------------ +- accepting +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Test case from RFC6455 4.2.2 */ +- memset (accept_key, 0, 29); +- ret = MHD_websocket_create_accept_header ("dGhlIHNhbXBsZSBub25jZQ==", +- accept_key); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (0 != memcmp (accept_key, "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", 29))) +- { +- fprintf (stderr, +- "Accept test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Missing parameters +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: missing sec-key value */ +- memset (accept_key, 0, 29); +- ret = MHD_websocket_create_accept_header (NULL, +- accept_key); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "Accept test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: missing accept variable */ +- memset (accept_key, 0, 29); +- ret = MHD_websocket_create_accept_header ("dGhlIHNhbXBsZSBub25jZQ==", +- NULL); +- if (MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) +- { +- fprintf (stderr, +- "Accept test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- return failed != 0 ? 0x02 : 0x00; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_decode()` +- */ +-int +-test_decodes () +-{ +- int failed = 0; +- char *buf1 = NULL, *buf2 = NULL; +- +- /* +- ------------------------------------------------------------------------------ +- text frame +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Masked text frame from RFC 6455, must succeed for server */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58", +- 11, +- "Hello", +- 5, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 11); +- /* Regular test: Unmasked text frame from RFC 6455, must succeed for client */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x05\x48\x65\x6c\x6c\x6f", +- 7, +- "Hello", +- 5, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 7); +- /* Fail test: Unmasked text frame from RFC 6455, must fail for server */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x05\x48\x65\x6c\x6c\x6f", +- 7, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Fail test: Masked text frame from RFC 6455, must fail for client */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Regular test: Text frame with UTF-8 sequence */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x90\x00\x00\x00\x00" "This is my n" +- "\xC3\xB6" "te", +- 22, +- "This is my n" "\xC3\xB6" "te", +- 16, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 22); +- /* Fail test: Text frame with with invalid UTF-8 */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8F\x00\x00\x00\x00" "This is my n" "\xFF" +- "te", +- 21, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 18); +- /* Fail test: Text frame with broken UTF-8 sequence */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8F\x00\x00\x00\x00" "This is my n" "\xC3" +- "te", +- 21, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 19); +- /* Regular test: Text frame without payload and mask (caller = server) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x80\x01\x02\x03\x04", +- 6, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 6); +- /* Fail test: Text frame without payload and no mask (caller = server) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x00", +- 2, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Regular test: Text frame without payload and mask (caller = client) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x00", +- 2, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 2); +- /* Fail test: Text frame without payload and no mask (caller = client) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x80\x01\x02\x03\x04", +- 6, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- +- /* +- ------------------------------------------------------------------------------ +- binary frame +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Masked binary frame (decoder = server) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x82\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58", +- 11, +- "Hello", +- 5, +- MHD_WEBSOCKET_STATUS_BINARY_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 11); +- /* Regular test: Unmasked binary frame (decoder = client) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x82\x05\x48\x65\x6c\x6c\x6f", +- 7, +- "Hello", +- 5, +- MHD_WEBSOCKET_STATUS_BINARY_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 7); +- /* Fail test: Unmasked binary frame (decoder = server) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x82\x05\x48\x65\x6c\x6c\x6f", +- 7, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Fail test: Masked binary frame (decoder = client) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x82\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Regular test: Binary frame without payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x82\x80\x00\x00\x00\x00", +- 6, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_BINARY_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 6); +- /* Regular test: Fragmented binary frame without payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x02\x80\x00\x00\x00\x00\x80\x80\x00\x00\x00\x00", +- 12, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_BINARY_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 12); +- /* Regular test: Fragmented binary frame without payload, fragments to the caller, 1st call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x02\x80\x00\x00\x00\x00\x80\x80\x00\x00\x00\x00", +- 12, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 6); +- /* Regular test: Fragmented binary frame without payload, fragments to the caller, 2nd call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x02\x80\x00\x00\x00\x00\x80\x80\x00\x00\x00\x00", +- 12, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_BINARY_LAST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 12); +- /* Regular test: Fragmented binary frame with payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x80\x83\x00\x00\x00\x00\x04\x05\x06", +- 18, +- "\x01\x02\x03\x04\x05\x06", +- 6, +- MHD_WEBSOCKET_STATUS_BINARY_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 18); +- /* Regular test: Fragmented binary frame with payload, fragments to the caller, 1st call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x80\x83\x00\x00\x00\x00\x04\x05\x06", +- 18, +- "\x01\x02\x03", +- 3, +- MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 9); +- /* Regular test: Fragmented binary frame without payload, fragments to the caller, 2nd call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x80\x83\x00\x00\x00\x00\x04\x05\x06", +- 18, +- "\x04\x05\x06", +- 3, +- MHD_WEBSOCKET_STATUS_BINARY_LAST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 18); +- /* Regular test: Fragmented binary frame with payload, fragments to the caller, 1st call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x00\x83\x00\x00\x00\x00\x04\x05\x06\x00\x83\x00\x00\x00\x00\x07\x08\x09\x80\x83\x00\x00\x00\x00\x0A\x0B\x0C", +- 36, +- "\x01\x02\x03", +- 3, +- MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 9); +- /* Regular test: Fragmented binary frame without payload, fragments to the caller, 2nd call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x00\x83\x00\x00\x00\x00\x04\x05\x06\x00\x83\x00\x00\x00\x00\x07\x08\x09\x80\x83\x00\x00\x00\x00\x0A\x0B\x0C", +- 36, +- "\x04\x05\x06", +- 3, +- MHD_WEBSOCKET_STATUS_BINARY_NEXT_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 18); +- /* Regular test: Fragmented binary frame without payload, fragments to the caller, 3rd call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 3, +- 0, +- "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x00\x83\x00\x00\x00\x00\x04\x05\x06\x00\x83\x00\x00\x00\x00\x07\x08\x09\x80\x83\x00\x00\x00\x00\x0A\x0B\x0C", +- 36, +- "\x07\x08\x09", +- 3, +- MHD_WEBSOCKET_STATUS_BINARY_NEXT_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 27); +- /* Regular test: Fragmented binary frame without payload, fragments to the caller, 4th call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 4, +- 0, +- "\x02\x83\x00\x00\x00\x00\x01\x02\x03\x00\x83\x00\x00\x00\x00\x04\x05\x06\x00\x83\x00\x00\x00\x00\x07\x08\x09\x80\x83\x00\x00\x00\x00\x0A\x0B\x0C", +- 36, +- "\x0A\x0B\x0C", +- 3, +- MHD_WEBSOCKET_STATUS_BINARY_LAST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 36); +- /* Regular test: Binary frame with bytes which look like invalid UTF-8 character */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x82\x85\x00\x00\x00\x00" "Hell\xf6", +- 11, +- "Hell\xf6", +- 5, +- MHD_WEBSOCKET_STATUS_BINARY_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 11); +- /* Regular test: Binary frame with bytes which look like broken UTF-8 sequence */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x82\x85\x00\x00\x00\x00" "H\xC3llo", +- 11, +- "H\xC3llo", +- 5, +- MHD_WEBSOCKET_STATUS_BINARY_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 11); +- /* Regular test: Binary frame with bytes which look like valid UTF-8 sequence */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x82\x85\x00\x00\x00\x00" "H\xC3\xA4lo", +- 11, +- "H\xC3\xA4lo", +- 5, +- MHD_WEBSOCKET_STATUS_BINARY_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 11); +- /* Regular test: Fragmented binary frame with bytes which look like valid UTF-8 sequence */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x02\x82\x00\x00\x00\x00" "H\xC3" +- "\x80\x83\x00\x00\x00\x00" "\xA4lo", +- 17, +- "H\xC3\xA4lo", +- 5, +- MHD_WEBSOCKET_STATUS_BINARY_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 17); +- /* Regular test: Fragmented binary frame with bytes which look like valid UTF-8 sequence, +- fragments to the caller, 1st call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x02\x82\x00\x00\x00\x00" "H\xC3" +- "\x80\x83\x00\x00\x00\x00" "\xA4lo", +- 17, +- "H\xC3", +- 2, +- MHD_WEBSOCKET_STATUS_BINARY_FIRST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 8); +- /* Regular test: Fragmented binary frame with bytes which look like valid UTF-8 sequence, +- fragments to the caller, 2nd call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x02\x82\x00\x00\x00\x00" "H\xC3" +- "\x80\x83\x00\x00\x00\x00" "\xA4lo", +- 17, +- "\xA4lo", +- 3, +- MHD_WEBSOCKET_STATUS_BINARY_LAST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 17); +- +- /* +- ------------------------------------------------------------------------------ +- close frame +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Close frame with no payload but with mask (decoder = server) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\x80\x00\x00\x00\x00", +- 6, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- 6); +- /* Regular test: Close frame with no payload (decoder = client) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\x00", +- 2, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- 2); +- /* Fail test: Close frame with no payload and no mask (decoder = server) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\x00", +- 2, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Fail test: Close frame with no payload but with mask (decoder = client) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\x80\x00\x00\x00\x00", +- 6, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Regular test: Close frame with 2 byte payload for close reason */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\x82\x00\x00\x00\x00\x03\xEB", +- 8, +- "\x03\xEB", +- 2, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- 8); +- /* Fail test: Close frame with 1 byte payload (no valid close reason) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\x81\x00\x00\x00\x00\x03", +- 7, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Regular test: Close frame with close reason and UTF-8 description */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\x95\x00\x00\x00\x00\x03\xEB" +- "Something was wrong", +- 27, +- "\x03\xEB" "Something was wrong", +- 21, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- 27); +- /* Regular test: Close frame with close reason and UTF-8 description (with UTF-8 sequence) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\x96\x00\x00\x00\x00\x03\xEB" +- "Something was wr" "\xC3\xB6" "ng", +- 28, +- "\x03\xEB" "Something was wr" "\xC3\xB6" "ng", +- 22, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- 28); +- /* Fail test: Close frame with close reason and invalid UTF-8 in description */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\x95\x00\x00\x00\x00\x03\xEB" +- "Something was wr" "\xFF" "ng", +- 27, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 24); +- /* Fail test: Close frame with close reason and broken UTF-8 sequence in description */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\x95\x00\x00\x00\x00\x03\xEB" +- "Something was wr" "\xC3" "ng", +- 27, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 25); +- /* Edge test (success): Close frame with 125 bytes of payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\xFD\x00\x00\x00\x00\x03\xEB" +- "Something was wrong, so I decided to close this websocket. I hope you are not angry. But this is also the 123 cap test. :-)", +- 131, +- "\x03\xEB" +- "Something was wrong, so I decided to close this websocket. I hope you are not angry. But this is also the 123 cap test. :-)", +- 125, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- 131); +- /* Edge test (failure): Close frame with 126 bytes of payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\xFE\x00\x7e\x00\x00\x00\x00\x03\xEB" +- "Something was wrong, so I decided to close this websocket. I hope you are not angry. But this is also the 123 cap test. >:-)", +- 134, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Fail test: Close frame with 500 bytes of payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\xFE\x01\xf4\x00\x00\x00\x00\x03\xEB" +- "The payload of this test isn't parsed.", +- 49, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Edge test (failure): Close frame with 65535 bytes of payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\xFE\xff\xff\x00\x00\x00\x00\x03\xEB" +- "The payload of this test isn't parsed.", +- 49, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Edge test (failure): Close frame with 65536 bytes of payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\xFF\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03\xEB" +- "The payload of this test isn't parsed.", +- 54, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Fail test: Close frame with 1000000 bytes of payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\xFF\x00\x00\x00\x00\x00\x0F\x42\x40\x00\x00\x00\x00\x03\xEB" +- "The payload of this test isn't parsed.", +- 54, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- +- /* +- ------------------------------------------------------------------------------ +- ping frame +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Ping frame with no payload but with mask (decoder = server) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x89\x80\x00\x00\x00\x00", +- 6, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 6); +- /* Regular test: Ping frame with no payload (decoder = client) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x89\x00", +- 2, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 2); +- /* Fail test: Ping frame with no payload and no mask (decoder = server) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x89\x00", +- 2, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Fail test: Ping frame with no payload but with mask (decoder = client) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x89\x80\x00\x00\x00\x00", +- 6, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Regular test: Ping frame with some (masked) payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x89\x88\x01\x20\x03\x40\xFF\xFF\xFF\xFF\x00\x00\x00\x00", +- 14, +- "\xFE\xDF\xFC\xBF\x01\x20\x03\x40", +- 8, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 14); +- /* Edge test (success): Ping frame with one byte of payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x89\x81\x00\x00\x00\x00" "a", +- 7, +- "a", +- 1, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 7); +- /* Edge test (success): Ping frame with 125 bytes of payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x89\xFD\x00\x00\x00\x00" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 131, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 125, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 131); +- /* Edge test (fail): Ping frame with 126 bytes of payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x89\xFE\x00\x7E\x00\x00\x00\x00" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", +- 134, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Regular test: Ping frame with UTF-8 data */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x89\x90\x00\x00\x00\x00" "Ping is bin" +- "\xC3\xA4" "ry.", +- 22, +- "Ping is bin" "\xC3\xA4" "ry.", +- 16, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 22); +- /* Regular test: Ping frame with invalid UTF-8 data */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x89\x8F\x00\x00\x00\x00" "Ping is bin" "\xFF" +- "ry.", +- 21, +- "Ping is bin" "\xFF" "ry.", +- 15, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 21); +- /* Regular test: Ping frame with broken UTF-8 sequence */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x89\x8F\x00\x00\x00\x00" "Ping is bin" "\xC3" +- "ry.", +- 21, +- "Ping is bin" "\xC3" "ry.", +- 15, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 21); +- +- /* +- ------------------------------------------------------------------------------ +- pong frame +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Pong frame with no payload but with mask (decoder = server) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8A\x80\x00\x00\x00\x00", +- 6, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 6); +- /* Regular test: Pong frame with no payload (decoder = client) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8A\x00", +- 2, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 2); +- /* Fail test: Pong frame with no payload and no mask (decoder = server) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8A\x00", +- 2, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Fail test: Pong frame with no payload but with mask (decoder = client) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_CLIENT +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8A\x80\x00\x00\x00\x00", +- 6, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Regular test: Pong frame with some (masked) payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8A\x88\x01\x20\x03\x40\xFF\xFF\xFF\xFF\x00\x00\x00\x00", +- 14, +- "\xFE\xDF\xFC\xBF\x01\x20\x03\x40", +- 8, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 14); +- /* Edge test (success): Pong frame with one byte of payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8A\x81\x00\x00\x00\x00" "a", +- 7, +- "a", +- 1, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 7); +- /* Edge test (success): Pong frame with 125 bytes of payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8A\xFD\x00\x00\x00\x00" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 131, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 125, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 131); +- /* Edge test (fail): Pong frame with 126 bytes of payload */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8A\xFE\x00\x7E\x00\x00\x00\x00" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", +- 134, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 1); +- /* Regular test: Pong frame with UTF-8 data */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8A\x90\x00\x00\x00\x00" "Pong is bin" +- "\xC3\xA4" "ry.", +- 22, +- "Pong is bin" "\xC3\xA4" "ry.", +- 16, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 22); +- /* Regular test: Pong frame with invalid UTF-8 data */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8A\x8F\x00\x00\x00\x00" "Pong is bin" "\xFF" +- "ry.", +- 21, +- "Pong is bin" "\xFF" "ry.", +- 15, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 21); +- /* Regular test: Pong frame with broken UTF-8 sequence */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8A\x8F\x00\x00\x00\x00" "Pong is bin" "\xC3" +- "ry.", +- 21, +- "Pong is bin" "\xC3" "ry.", +- 15, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 21); +- +- /* +- ------------------------------------------------------------------------------ +- fragmentation +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Fragmented, masked text frame, we are the server and don't want fragments as caller */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x80\x82\x3d\x37\xfa\x21\x51\x58", +- 17, +- "Hello", +- 5, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 17); +- /* Regular test: Fragmented, masked text frame, we are the server and don't want fragments as caller, but call decode two times */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x80\x82\x3d\x37\xfa\x21\x51\x58", +- 17, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_OK, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 17); +- /* Regular test: Fragmented, masked text frame, we are the server and want fragments, one call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x80\x82\x3d\x37\xfa\x21\x51\x58", +- 17, +- "Hel", +- 3, +- MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 9); +- /* Regular test: Fragmented, masked text frame, we are the server and want fragments, second call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x80\x82\x3d\x37\xfa\x21\x51\x58", +- 17, +- "lo", +- 2, +- MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 17); +- /* Regular test: Fragmented, masked text frame, we are the server and want fragments, third call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 3, +- 0, +- "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x80\x82\x3d\x37\xfa\x21\x51\x58", +- 17, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_OK, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 17); +- /* Regular test: Fragmented, masked text frame, we are the server and want fragments, 1st call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x00\x81\x3d\x37\xfa\x21\x51\x80\x81\x37\x37\xfa\x21\x58", +- 23, +- "Hel", +- 3, +- MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 9); +- /* Regular test: Fragmented, masked text frame, we are the server and want fragments, 2nd call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x00\x81\x3d\x37\xfa\x21\x51\x80\x81\x37\x37\xfa\x21\x58", +- 23, +- "l", +- 1, +- MHD_WEBSOCKET_STATUS_TEXT_NEXT_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Regular test: Fragmented, masked text frame, we are the server and want fragments, 3rd call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 3, +- 0, +- "\x01\x83\x37\xfa\x21\x3d\x7f\x9f\x4d\x00\x81\x3d\x37\xfa\x21\x51\x80\x81\x37\x37\xfa\x21\x58", +- 23, +- "o", +- 1, +- MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 23); +- +- +- /* +- ------------------------------------------------------------------------------ +- invalid flags +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Template with valid data for the next tests (this one must succeed) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x85\x00\x00\x00\x00Hello", +- 11, +- "Hello", +- 5, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 11); +- /* Fail test: RSV1 flag set */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x91\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: RSV2 flag set */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\xA1\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: RSV3 flag set */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\xC1\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- +- /* +- ------------------------------------------------------------------------------ +- invalid opcodes +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: Invalid opcode 0 (0 is usually valid, but only if there was a data frame before) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x80\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: Invalid opcode 3 */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x83\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: Invalid opcode 4 */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x84\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: Invalid opcode 5 */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x85\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: Invalid opcode 6 */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x86\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: Invalid opcode 7 */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x87\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: Invalid opcode 0x0B */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8B\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: Invalid opcode 0x0C */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8c\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: Invalid opcode 0x0D */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8d\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: Invalid opcode 0x0E */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8e\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: Invalid opcode 0x0F */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x8f\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- +- +- /* +- ------------------------------------------------------------------------------ +- control frames without FIN flag +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: Close frame without FIN flag */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x08\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: Ping frame without FIN flag */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x09\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Fail test: Pong frame without FIN flag */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x0a\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- +- /* +- ------------------------------------------------------------------------------ +- length checks (without max_payload_len) +- ------------------------------------------------------------------------------ +- */ +- /* Edge test (success): 0 bytes of payload (requires 1 byte length) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x80\x00\x00\x00\x00", +- 6, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 6); +- /* Edge test (success): 1 byte of payload (requires 1 byte length) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x81\x00\x00\x00\x00" "a", +- 7, +- "a", +- 1, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 7); +- /* Edge test (success): 125 bytes of payload (requires 1 byte length) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\xfd\x00\x00\x00\x00" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 131, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 125, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 131); +- /* Edge test (success): 126 bytes of payload (requires 2 byte length) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\xfe\x00\x7e\x00\x00\x00\x00" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", +- 134, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", +- 126, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 134); +- /* Edge test (success): 65535 bytes of payload (requires 2 byte length) */ +- allocate_length_test_data (&buf1, +- &buf2, +- 65535, +- "\x81\xfe\xff\xff\x00\x00\x00\x00", +- 8); +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- buf1, +- 65535 + 8, +- buf2, +- 65535, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 65535 + 8); +- /* Edge test (success): 65536 bytes of payload (requires 8 byte length) */ +- allocate_length_test_data (&buf1, +- &buf2, +- 65536, +- "\x81\xff\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00", +- 14); +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- buf1, +- 65536 + 14, +- buf2, +- 65536, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 65536 + 14); +- /* Regular test: 1 MB of payload */ +- allocate_length_test_data (&buf1, +- &buf2, +- 1048576, +- "\x81\xff\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00", +- 14); +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- buf1, +- 1048576 + 14, +- buf2, +- 1048576, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 1048576 + 14); +- /* Regular test: 100 MB of payload */ +- allocate_length_test_data (&buf1, +- &buf2, +- 104857600, +- "\x81\xff\x00\x00\x00\x00\x06\x40\x00\x00\x00\x00\x00\x00", +- 14); +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- buf1, +- 104857600 + 14, +- buf2, +- 104857600, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 104857600 + 14); +- if (NULL != buf1) +- { +- free (buf1); +- buf1 = NULL; +- } +- if (NULL != buf2) +- { +- free (buf2); +- buf2 = NULL; +- } +-#ifdef ENABLE_64BIT_TESTS +- /* Edge test (success): Maximum allowed length (here is only the header checked) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\xff\x7f\xff\xff\xff\xff\xff\xff\xff", +- 10, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_OK, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 10); +-#else +- /* Edge test (fail): Maximum allowed length +- (the size is allowed, but the system cannot handle this amount of memory) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\xff\x7f\xff\xff\xff\xff\xff\xff\xff", +- 10, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 10); +-#endif +- /* Edge test (fail): Too big payload length */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\xff\x80\x00\x00\x00\x00\x00\x00\x00", +- 10, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 10); +- /* Edge test (fail): Too big payload length */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\xff\xff\xff\xff\xff\xff\xff\xff\xff", +- 10, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 10); +- /* Fail test: Not the smallest payload length syntax used (2 byte instead of 1 byte) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\xfe\x00\x05\x00\x00\x00\x00" "abcde", +- 13, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 4); +- /* Fail test: Not the smallest payload length syntax used (8 byte instead of 1 byte) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\xff\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00" +- "abcde", +- 13, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 10); +- /* Fail test: Not the smallest payload length syntax used (8 byte instead of 2 byte) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\xff\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00" +- "abcde", +- 13, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 10); +- +- /* +- ------------------------------------------------------------------------------ +- length checks (with max_payload_len) +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Frame with less payload than specified as limit */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 100, +- 1, +- 0, +- "\x81\x85\x00\x00\x00\x00" "Hello", +- 11, +- "Hello", +- 5, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 11); +- /* Edge test (success): Frame with the same payload as the specified limit */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 5, +- 1, +- 0, +- "\x81\x85\x00\x00\x00\x00" "Hello", +- 11, +- "Hello", +- 5, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 11); +- /* Edge test (fail): Frame with more payload than specified as limit */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 4, +- 1, +- 0, +- "\x81\x85\x00\x00\x00\x00" "Hello", +- 11, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 2); +- /* Regular test: Fragmented frames with the sum of payload less than specified as limit */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 100, +- 1, +- 0, +- "\x01\x83\x00\x00\x00\x00" +- "Hel\x80\x82\x00\x00\x00\x00" "lo", +- 17, +- "Hello", +- 5, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 17); +- /* Edge test (success): Fragmented frames with the sum of payload equal to the specified limit */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 5, +- 1, +- 0, +- "\x01\x83\x00\x00\x00\x00" +- "Hel\x80\x82\x00\x00\x00\x00" "lo", +- 17, +- "Hello", +- 5, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 17); +- /* Edge test (fail): Fragmented frames with the sum of payload more than specified as limit */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 4, +- 1, +- 0, +- "\x01\x83\x00\x00\x00\x00" +- "Hel\x80\x82\x00\x00\x00\x00" "lo", +- 17, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 15); +- /* Edge test (success): Fragmented frames with the sum of payload greater than +- the specified limit, but we take fragments (one call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 5, +- 1, +- 0, +- "\x01\x83\x00\x00\x00\x00" +- "Hel\x80\x82\x00\x00\x00\x00" "lo", +- 17, +- "Hel", +- 3, +- MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 9); +- /* Edge test (success): Fragmented frames with the sum of payload greater than +- the specified limit, but we take fragments (two calls) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 5, +- 2, +- 0, +- "\x01\x83\x00\x00\x00\x00" +- "Hel\x80\x82\x00\x00\x00\x00" "lo", +- 17, +- "lo", +- 2, +- MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 17); +- +- /* +- ------------------------------------------------------------------------------ +- UTF-8 sequences +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: No UTF-8 characters */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 a ", +- 16, +- " a ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Fail test: A UTF-8 tail character without sequence start character */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xA4 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 7); +- /* Regular test: A two byte UTF-8 sequence */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xC3\xA4 ", +- 16, +- " \xC3\xA4 ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Fail test: A broken two byte UTF-8 sequence */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xC3 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Fail test: A two byte UTF-8 sequence with one UTF-8 tail too much */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xC3\xA4\xA4 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 9); +- /* Regular test: A three byte UTF-8 sequence */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xEF\x8F\x8F ", +- 16, +- " \xEF\x8F\x8F ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Fail test: A broken byte UTF-8 sequence (two of three bytes) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xEF\x8F ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 9); +- /* Fail test: A broken byte UTF-8 sequence (one of three bytes) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xEF ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Fail test: A three byte UTF-8 sequence followed by one UTF-8 tail byte */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xEF\x8F\x8F\x8F ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 10); +- /* Regular test: A four byte UTF-8 sequence */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF2\x8F\x8F\x8F ", +- 16, +- " \xF2\x8F\x8F\x8F ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Fail test: A broken four byte UTF-8 sequence (three of four bytes) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF2\x8F\x8F ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 10); +- /* Fail test: A broken four byte UTF-8 sequence (two of four bytes) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF2\x8F ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 9); +- /* Fail test: A broken four byte UTF-8 sequence (one of four bytes) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF2 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Fail test: A four byte UTF-8 sequence followed by UTF-8 tail */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF2\x8F\x8F\x8F\x8F ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 11); +- /* Fail test: A five byte UTF-8 sequence (only up to four bytes allowed) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xFB\x8F\x8F\x8F\x8F ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 7); +- /* Fail test: A six byte UTF-8 sequence (only up to four bytes allowed) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xFD\x8F\x8F\x8F\x8F\x8F ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 7); +- /* Fail test: A seven byte UTF-8 sequence (only up to four bytes allowed) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xFE\x8F\x8F\x8F\x8F\x8F\x8F ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 7); +- /* Fail test: A eight byte UTF-8 sequence (only up to four bytes allowed) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xFF\x8F\x8F\x8F\x8F\x8F\x8F\x8F ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 7); +- /* Edge test (success): The maximum allowed UTF-8 character */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF4\x8F\xBF\xBF ", +- 16, +- " \xF4\x8F\xBF\xBF ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (fail): The maximum allowed UTF-8 character + 1 */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF4\x90\x80\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (success): The last valid UTF8-1 character */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \x7F ", +- 16, +- " \x7F ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (fail): The value after the last valid UTF8-1 character */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 7); +- /* Edge test (fail): The value before the first valid UTF8-2 character */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xC1\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 7); +- /* Edge test (success): The first valid UTF8-2 character */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xC2\x80 ", +- 16, +- " \xC2\x80 ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (success): The last valid UTF8-2 character */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xDF\xBF ", +- 16, +- " \xDF\xBF ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (fail): The value after the lst valid UTF8-2 character */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xE0\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (fail): The value before the first valid UTF8-3 character (tail 1) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xE0\x9F\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (success): The first valid UTF8-3 character (tail 1) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xE0\xA0\x80 ", +- 16, +- " \xE0\xA0\x80 ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (success): The last valid UTF8-3 character (tail 1) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xE0\xBF\xBF ", +- 16, +- " \xE0\xBF\xBF ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (fail): The value after the first valid UTF8-3 character (tail 1) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xE0\xC0\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (success): The first valid UTF8-3 character (tail 2) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xE1\x80\x80 ", +- 16, +- " \xE1\x80\x80 ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (success): The last valid UTF8-3 character (tail 2) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xEC\xBF\xBF ", +- 16, +- " \xEC\xBF\xBF ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (fail): The value after the last valid UTF8-3 character (tail 2) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xEC\xC0\xBF ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (fail): The value before the first valid UTF8-3 character (tail 3) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xED\x7F\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (success): The first valid UTF8-3 character (tail 3) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xED\x80\x80 ", +- 16, +- " \xED\x80\x80 ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (success): The last valid UTF8-3 character (tail 3) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xED\x9F\xBF ", +- 16, +- " \xED\x9F\xBF ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (fail): The value after the last valid UTF8-3 character (tail 3) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xED\xA0\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (fail): The value before the first valid UTF8-3 character (tail 4) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xEE\x7F\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (success): The first valid UTF8-3 character (tail 4) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xEE\x80\x80 ", +- 16, +- " \xEE\x80\x80 ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (success): The last valid UTF8-3 character (tail 4) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xEF\xBF\xBF ", +- 16, +- " \xEF\xBF\xBF ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (fail): The value after the last valid UTF8-3 character (tail 4) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xEF\xBF\xC0 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 9); +- /* Edge test (fail): The value after the last valid UTF8-3 character (tail 4) #2 */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xEF\xC0\xBF ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (fail): The value before the first valid UTF8-4 character (tail 1) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF0\x8F\x80\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (success): The first valid UTF8-4 character (tail 1) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF0\x90\x80\x80 ", +- 16, +- " \xF0\x90\x80\x80 ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (success): The last valid UTF8-4 character (tail 1) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF0\xBF\xBF\xBF ", +- 16, +- " \xF0\xBF\xBF\xBF ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (success): The first valid UTF8-4 character (tail 2) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF1\x80\x80\x80 ", +- 16, +- " \xF1\x80\x80\x80 ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (success): The last valid UTF8-4 character (tail 2) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF3\xBF\xBF\xBF ", +- 16, +- " \xF3\xBF\xBF\xBF ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (fail): A value before the last valid UTF8-4 character in the second byte (tail 2) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF3\x7F\x80\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (fail): A value after the last valid UTF8-4 character in the second byte (tail 2) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF3\xC0\x80\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (success): The first valid UTF8-4 character (tail 3) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF4\x80\x80\x80 ", +- 16, +- " \xF4\x80\x80\x80 ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (success): The last valid UTF8-4 character (tail 3) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF4\x8F\xBF\xBF ", +- 16, +- " \xF4\x8F\xBF\xBF ", +- 10, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 16); +- /* Edge test (fail): The value after the last valid UTF8-4 character (tail 3) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF4\x90\x80\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 8); +- /* Edge test (fail): The first byte value the last valid UTF8-4 character */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x8A\x00\x00\x00\x00 \xF5\x90\x80\x80 ", +- 16, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 7); +- +- /* +- ------------------------------------------------------------------------------ +- Unfinished UTF-8 sequence between fragmented text frame +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: UTF-8 sequence between fragments, no fragmentation for the caller */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x8D\x00\x00\x00\x00" "This is my n" +- "\xC3\x80\x83\x00\x00\x00\x00\xB6" "te", +- 28, +- "This is my n" "\xC3\xB6" "te", +- 16, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 28); +- /* Regular test: UTF-8 sequence between fragments, fragmentation for the caller, 1st call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x8D\x00\x00\x00\x00" "This is my n" +- "\xC3\x80\x83\x00\x00\x00\x00\xB6" "te", +- 28, +- "This is my n", +- 12, +- MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 19); +- /* Regular test: UTF-8 sequence between fragments, fragmentation for the caller, 2nd call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x01\x8D\x00\x00\x00\x00" "This is my n" +- "\xC3\x80\x83\x00\x00\x00\x00\xB6" "te", +- 28, +- "\xC3\xB6" "te", +- 4, +- MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 28); +- /* Edge test (success): UTF-8 sequence between fragments, but nothing before, fragmentation for the caller, 1st call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x81\x00\x00\x00\x00\xC3\x80\x81\x00\x00\x00\x00\xB6", +- 14, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 7); +- /* Edge test (success): UTF-8 sequence between fragments, but nothing before, fragmentation for the caller, 2nd call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x01\x81\x00\x00\x00\x00\xC3\x80\x81\x00\x00\x00\x00\xB6", +- 14, +- "\xC3\xB6", +- 2, +- MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 14); +- +- /* +- ------------------------------------------------------------------------------ +- Decoding with broken stream +- ------------------------------------------------------------------------------ +- */ +- /* Failure test: Invalid sequence */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\xFF\x81\x85\x00\x00\x00\x00" "Hello", +- 12, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Failure test: Call after invalidated stream */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 2, +- 0, +- "\xFF\x81\x85\x00\x00\x00\x00" "Hello", +- 12, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_STREAM_BROKEN, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Failure test: Call after invalidated stream (but with different buffer) */ +- { +- struct MHD_WebSocketStream *ws; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | +- MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0)) +- { +- size_t streambuf_read_len = 0; +- char *payload = NULL; +- size_t payload_len = 0; +- int ret = 0; +- ret = MHD_websocket_decode (ws, +- "\xFF", +- 1, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if (MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR != ret) +- { +- fprintf (stderr, +- "Test failed in line %u: The return value should be -1, but is %d\n", +- (unsigned int) __LINE__, +- (int) ret); +- ++failed; +- } +- else +- { +- ret = MHD_websocket_decode (ws, +- "\x81\x85\x00\x00\x00\x00" "Hello", +- 11, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if (MHD_WEBSOCKET_STATUS_STREAM_BROKEN != ret) +- { +- fprintf (stderr, +- "Test failed in line %u: The return value should be -2, but is %d\n", +- (unsigned int) __LINE__, +- (int) ret); +- ++failed; +- } +- } +- MHD_websocket_stream_free (ws); +- } +- else +- { +- fprintf (stderr, +- "Individual test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- +- /* +- ------------------------------------------------------------------------------ +- frame after close frame +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Close frame */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x88\x80\x00\x00\x00\x00\x81\x85\x00\x00\x00\x00" +- "Hello", +- 17, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- 6); +- /* Failure test: Text frame after close frame */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x88\x80\x00\x00\x00\x00\x81\x85\x00\x00\x00\x00" +- "Hello", +- 17, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 6); +- /* Failure test: Binary frame after close frame */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x88\x80\x00\x00\x00\x00\x82\x85\x00\x00\x00\x00" +- "Hello", +- 17, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 6); +- /* Failure test: Continue frame after close frame */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x88\x80\x00\x00\x00\x00\x80\x85\x00\x00\x00\x00" +- "Hello", +- 17, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 6); +- /* Regular test: Ping frame after close frame */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x88\x80\x00\x00\x00\x00\x89\x85\x00\x00\x00\x00" +- "Hello", +- 17, +- "Hello", +- 5, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- 17); +- /* Regular test: Pong frame after close frame */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x88\x80\x00\x00\x00\x00\x8A\x85\x00\x00\x00\x00" +- "Hello", +- 17, +- "Hello", +- 5, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- 17); +- /* Regular test: Close frame after close frame */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x88\x80\x00\x00\x00\x00\x88\x80\x00\x00\x00\x00", +- 12, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- 12); +- +- /* +- ------------------------------------------------------------------------------ +- decoding byte-by-byte +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Text frame, 2 bytes per loop, 1st call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 2, +- "\x81\x91\x01\x02\x04\x08" "Ujm{!kw(uja(ugw|/", +- 23, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_OK, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 2); +- /* Regular test: Text frame, 2 bytes per loop, 11th call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 11, +- 2, +- "\x81\x91\x01\x02\x04\x08" "Ujm{!kw(uja(ugw|/", +- 23, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_OK, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 22); +- /* Regular test: Text frame, 2 bytes per loop, 12th call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 12, +- 2, +- "\x81\x91\x01\x02\x04\x08" "Ujm{!kw(uja(ugw|/", +- 23, +- "This is the test.", +- 17, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 23); +- /* Regular test: Text frame, 1 byte per loop, 1st call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 1, +- "\x81\x91\x01\x02\x04\x08" "Ujm{!kw(uja(ugw|/", +- 23, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_OK, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 1); +- /* Regular test: Text frame, 1 byte per loop, 22nd call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 22, +- 1, +- "\x81\x91\x01\x02\x04\x08" "Ujm{!kw(uja(ugw|/", +- 23, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_OK, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 22); +- /* Regular test: Text frame, 1 byte per loop, 23rd call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 23, +- 1, +- "\x81\x91\x01\x02\x04\x08" "Ujm{!kw(uja(ugw|/", +- 23, +- "This is the test.", +- 17, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 23); +- +- /* +- ------------------------------------------------------------------------------ +- mix of fragmented data frames and control frames +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Fragmented text frame mixed with one ping frame (1st call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x89\x80\x00\x00\x00\x00" +- "\x80\x8C\x00\x00\x00\x00" "is the test.", +- 35, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 17); +- /* Regular test: Fragmented text frame mixed with one ping frame (2nd call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x89\x80\x00\x00\x00\x00" +- "\x80\x8C\x00\x00\x00\x00" "is the test.", +- 35, +- "This is the test.", +- 17, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 35); +- /* Regular test: Fragmented text frame mixed with one close frame (1st call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x88\x80\x00\x00\x00\x00" +- "\x80\x8C\x00\x00\x00\x00" "is the test.", +- 35, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- 17); +- /* Fail test: Fragmented text frame mixed with one ping frame (2nd call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x88\x80\x00\x00\x00\x00" +- "\x80\x8C\x00\x00\x00\x00" "is the test.", +- 35, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 17); +- /* Regular test: Fragmented text frame mixed with one ping frame, the caller wants fragments (1st call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x89\x80\x00\x00\x00\x00" +- "\x80\x8C\x00\x00\x00\x00" "is the test.", +- 35, +- "This ", +- 5, +- MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 11); +- /* Regular test: Fragmented text frame mixed with one ping frame, the caller wants fragments (2nd call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x89\x80\x00\x00\x00\x00" +- "\x80\x8C\x00\x00\x00\x00" "is the test.", +- 35, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 17); +- /* Regular test: Fragmented text frame mixed with one ping frame, the caller wants fragments (3rd call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 3, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x89\x80\x00\x00\x00\x00" +- "\x80\x8C\x00\x00\x00\x00" "is the test.", +- 35, +- "is the test.", +- 12, +- MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 35); +- +- /* +- ------------------------------------------------------------------------------ +- mix of fragmented data frames and data frames +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: Fragmented text frame mixed with one non-fragmented binary frame */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x82\x81\x00\x00\x00\x00" +- "a\x80\x8C\x00\x00\x00\x00" "is the test.", +- 36, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 11); +- /* Regular test: Fragmented text frame mixed with one non-fragmented binary frame; the caller wants fragments; 1st call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x82\x81\x00\x00\x00\x00" +- "a\x80\x8C\x00\x00\x00\x00" "is the test.", +- 36, +- "This ", +- 5, +- MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 11); +- /* Fail test: Fragmented text frame mixed with one non-fragmented binary frame; the caller wants fragments; 2nd call */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x82\x81\x00\x00\x00\x00" +- "a\x80\x8C\x00\x00\x00\x00" "is the test.", +- 36, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 11); +- /* Fail test: Fragmented text frame mixed with one fragmented binary frame */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x02\x81\x00\x00\x00\x00" +- "a\x80\x8C\x00\x00\x00\x00" "is the test.", +- 36, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 11); +- /* Fail test: Fragmented text frame, continue frame, non-fragmented binary frame */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x00\x8C\x00\x00\x00\x00" +- "is the test.\x82\x81\x00\x00\x00\x00" "a", +- 36, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 29); +- /* Fail test: Fragmented text frame, continue frame, fragmented binary frame */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x01\x85\x00\x00\x00\x00" +- "This \x00\x8C\x00\x00\x00\x00" +- "is the test.\x02\x81\x00\x00\x00\x00" "a", +- 36, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 29); +- +- /* +- ------------------------------------------------------------------------------ +- multiple data frames +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Text frame, binary frame, text frame (1st call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x81\x85\x00\x00\x00\x00" +- "This \x82\x87\x00\x00\x00\x00" +- "is the \x81\x85\x00\x00\x00\x00" "test.", +- 35, +- "This ", +- 5, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 11); +- /* Regular test: Text frame, binary frame, text frame (2nd call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x81\x85\x00\x00\x00\x00" +- "This \x82\x87\x00\x00\x00\x00" +- "is the \x81\x85\x00\x00\x00\x00" "test.", +- 35, +- "is the ", +- 7, +- MHD_WEBSOCKET_STATUS_BINARY_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 24); +- /* Regular test: Text frame, binary frame, text frame (3rd call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 3, +- 0, +- "\x81\x85\x00\x00\x00\x00" +- "This \x82\x87\x00\x00\x00\x00" +- "is the \x81\x85\x00\x00\x00\x00" "test.", +- 35, +- "test.", +- 5, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 35); +- /* +- ------------------------------------------------------------------------------ +- multiple control frames +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Ping frame, pong frame, close frame (1st call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- "\x89\x85\x00\x00\x00\x00" +- "This \x8A\x87\x00\x00\x00\x00" +- "is the \x88\x85\x00\x00\x00\x00" "test.", +- 35, +- "This ", +- 5, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 11); +- /* Regular test: Ping frame, pong frame, close frame (2nd call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 2, +- 0, +- "\x89\x85\x00\x00\x00\x00" +- "This \x8A\x87\x00\x00\x00\x00" +- "is the \x88\x85\x00\x00\x00\x00" "test.", +- 35, +- "is the ", +- 7, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- 24); +- /* Regular test: Ping frame, pong frame, close frame (3rd call) */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 3, +- 0, +- "\x89\x85\x00\x00\x00\x00" +- "This \x8A\x87\x00\x00\x00\x00" +- "is the \x88\x85\x00\x00\x00\x00" "test.", +- 35, +- "test.", +- 5, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- 35); +- +- /* +- ------------------------------------------------------------------------------ +- generated close frames for errors +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Close frame generated for protocol error */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS +- | +- MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR, +- 0, +- 1, +- 0, +- "\xFF", +- 1, +- "\x88\x02\x03\xEA", +- 4, +- MHD_WEBSOCKET_STATUS_PROTOCOL_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 0); +- /* Regular test: Close frame generated for UTF-8 sequence error */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS +- | +- MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR, +- 0, +- 1, +- 0, +- "\x81\x85\x00\x00\x00\x00T\xFFst.", +- 11, +- "\x88\x02\x03\xEF", +- 4, +- MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 7); +- /* Regular test: Close frame generated for message size exceeded */ +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS +- | +- MHD_WEBSOCKET_FLAG_GENERATE_CLOSE_FRAMES_ON_ERROR, +- 3, +- 1, +- 0, +- "\x81\x85\x00\x00\x00\x00T\xFFst.", +- 11, +- "\x88\x02\x03\xF1", +- 4, +- MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED, +- MHD_WEBSOCKET_VALIDITY_INVALID, +- 2); +- +- /* +- ------------------------------------------------------------------------------ +- terminating NUL character +- ------------------------------------------------------------------------------ +- */ +- { +- struct MHD_WebSocketStream *ws; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | +- MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0)) +- { +- size_t streambuf_read_len = 0; +- char *payload = NULL; +- size_t payload_len = 0; +- int ret = 0; +- +- /* Regular test: text frame */ +- ret = MHD_websocket_decode (ws, +- "\x81\x85\x00\x00\x00\x00" "Hello", +- 11, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_TEXT_FRAME != ret) || +- (5 != payload_len) || +- (NULL == payload) || +- (0 != memcmp ("Hello", payload, 5 + 1))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- payload = NULL; +- } +- +- /* Regular test: text frame fragment */ +- ret = MHD_websocket_decode (ws, +- "\x01\x83\x00\x00\x00\x00" +- "Hel\x80\x82\x00\x00\x00\x00" "lo", +- 17, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_TEXT_FRAME != ret) || +- (5 != payload_len) || +- (NULL == payload) || +- (0 != memcmp ("Hello", payload, 5 + 1))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- payload = NULL; +- } +- +- /* Regular test: binary frame */ +- ret = MHD_websocket_decode (ws, +- "\x82\x85\x00\x00\x00\x00" "Hello", +- 11, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_BINARY_FRAME != ret) || +- (5 != payload_len) || +- (NULL == payload) || +- (0 != memcmp ("Hello", payload, 5 + 1))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- payload = NULL; +- } +- +- /* Regular test: binary frame fragment */ +- ret = MHD_websocket_decode (ws, +- "\x02\x83\x00\x00\x00\x00" +- "Hel\x80\x82\x00\x00\x00\x00" "lo", +- 17, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_BINARY_FRAME != ret) || +- (5 != payload_len) || +- (NULL == payload) || +- (0 != memcmp ("Hello", payload, 5 + 1))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- payload = NULL; +- } +- +- MHD_websocket_stream_free (ws); +- } +- else +- { +- fprintf (stderr, +- "Individual decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- { +- struct MHD_WebSocketStream *ws; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | +- MHD_WEBSOCKET_FLAG_WANT_FRAGMENTS, +- 0)) +- { +- size_t streambuf_read_len = 0; +- char *payload = NULL; +- size_t payload_len = 0; +- int ret = 0; +- +- /* Regular test: text frame fragment (caller wants fragment, 1st call) */ +- ret = MHD_websocket_decode (ws, +- "\x01\x83\x00\x00\x00\x00" +- "Hel\x80\x82\x00\x00\x00\x00" "lo", +- 17, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT != ret) || +- (3 != payload_len) || +- (NULL == payload) || +- (0 != memcmp ("Hel", payload, 3 + 1))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- payload = NULL; +- } +- +- /* Regular test: text frame fragment (caller wants fragment, 2nd call) */ +- ret = MHD_websocket_decode (ws, +- "\x01\x83\x00\x00\x00\x00" +- "Hel\x80\x82\x00\x00\x00\x00" "lo" +- + streambuf_read_len, +- 17 - streambuf_read_len, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT != ret) || +- (2 != payload_len) || +- (NULL == payload) || +- (0 != memcmp ("lo", payload, 2 + 1))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- payload = NULL; +- } +- +- /* Regular test: text frame fragment with broken UTF-8 sequence (caller wants fragment, 1st call) */ +- ret = MHD_websocket_decode (ws, +- "\x01\x83\x00\x00\x00\x00" +- "He\xC3\x80\x82\x00\x00\x00\x00" "\xB6o", +- 17, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_TEXT_FIRST_FRAGMENT != ret) || +- (2 != payload_len) || +- (NULL == payload) || +- (0 != memcmp ("He", payload, 2 + 1))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- payload = NULL; +- } +- +- /* Regular test: text frame fragment with broken UTF-8 sequence (caller wants fragment, 2nd call) */ +- ret = MHD_websocket_decode (ws, +- "\x01\x83\x00\x00\x00\x00" +- "He\xC3\x80\x82\x00\x00\x00\x00" "\xB6o" +- + streambuf_read_len, +- 17 - streambuf_read_len, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_TEXT_LAST_FRAGMENT != ret) || +- (3 != payload_len) || +- (NULL == payload) || +- (0 != memcmp ("\xC3\xB6o", payload, 3 + 1))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- payload = NULL; +- } +- +- MHD_websocket_stream_free (ws); +- } +- else +- { +- fprintf (stderr, +- "Individual decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- +- +- /* +- ------------------------------------------------------------------------------ +- invalid parameters +- ------------------------------------------------------------------------------ +- */ +- { +- struct MHD_WebSocketStream *ws; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | +- MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0)) +- { +- size_t streambuf_read_len = 0; +- char *payload = NULL; +- size_t payload_len = 0; +- int ret = 0; +- +- /* Failure test: `ws` is NULL */ +- payload = (char *) (uintptr_t) 0xBAADF00D; +- payload_len = 0x87654321; +- streambuf_read_len = 1000; +- ret = MHD_websocket_decode (NULL, +- "\x81\x85\x00\x00\x00\x00Hello", +- 11, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != payload) || +- (0 != payload_len) || +- (0 != streambuf_read_len) || +- (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == payload) +- { +- payload = NULL; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- } +- /* Failure test: `buf` is NULL, while `buf_len` != 0 */ +- payload = (char *) (uintptr_t) 0xBAADF00D; +- payload_len = 0x87654321; +- streambuf_read_len = 1000; +- ret = MHD_websocket_decode (ws, +- NULL, +- 11, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != payload) || +- (0 != payload_len) || +- (0 != streambuf_read_len) || +- (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == payload) +- { +- payload = NULL; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- } +- /* Failure test: `streambuf_read_len` is NULL */ +- payload = (char *) (uintptr_t) 0xBAADF00D; +- payload_len = 0x87654321; +- ret = MHD_websocket_decode (ws, +- "\x81\x85\x00\x00\x00\x00Hello", +- 11, +- NULL, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != payload) || +- (0 != payload_len) || +- (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == payload) +- { +- payload = NULL; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- } +- /* Failure test: `payload` is NULL */ +- payload_len = 0x87654321; +- streambuf_read_len = 1000; +- ret = MHD_websocket_decode (ws, +- "\x81\x85\x00\x00\x00\x00Hello", +- 11, +- &streambuf_read_len, +- NULL, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != payload_len) || +- (0 != streambuf_read_len) || +- (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Failure test: `payload_len` is NULL */ +- payload = (char *) (uintptr_t) 0xBAADF00D; +- streambuf_read_len = 1000; +- ret = MHD_websocket_decode (ws, +- "\x81\x85\x00\x00\x00\x00Hello", +- 11, +- &streambuf_read_len, +- &payload, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != payload) || +- (0 != streambuf_read_len) || +- (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == payload) +- { +- payload = NULL; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- } +- /* Regular test: `buf` is NULL and `buf_len` is 0 */ +- payload = (char *) (uintptr_t) 0xBAADF00D; +- payload_len = 0x87654321; +- streambuf_read_len = 1000; +- ret = MHD_websocket_decode (ws, +- NULL, +- 0, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL != payload) || +- (0 != payload_len) || +- (0 != streambuf_read_len) || +- (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == payload) +- { +- payload = NULL; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- } +- /* Regular test: `buf` is not NULL and `buf_len` is 0 */ +- payload = (char *) (uintptr_t) 0xBAADF00D; +- payload_len = 0x87654321; +- streambuf_read_len = 1000; +- ret = MHD_websocket_decode (ws, +- "\x81\x85\x00\x00\x00\x00Hello", +- 0, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL != payload) || +- (0 != payload_len) || +- (0 != streambuf_read_len) || +- (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == payload) +- { +- payload = NULL; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- } +- +- MHD_websocket_stream_free (ws); +- } +- else +- { +- fprintf (stderr, +- "Parameter decode tests failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- +- /* +- ------------------------------------------------------------------------------ +- validity after temporary out-of-memory +- ------------------------------------------------------------------------------ +- */ +- { +- struct MHD_WebSocketStream *ws; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | +- MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL)) +- { +- size_t streambuf_read_len = 0; +- char *payload = NULL; +- size_t payload_len = 0; +- int ret = 0; +- +- /* Failure test: No memory allocation at the start */ +- disable_alloc = 1; +- payload = (char *) (uintptr_t) 0xBAADF00D; +- payload_len = 0x87654321; +- streambuf_read_len = 1000; +- ret = MHD_websocket_decode (ws, +- "\x81\x85\x00\x00\x00\x00Hello", +- 11, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || +- (NULL != payload) || +- (0 != payload_len) || +- (1000 == streambuf_read_len) || +- (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid (ws))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == payload) +- { +- payload = NULL; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- } +- MHD_websocket_stream_free (ws); +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | +- MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL)) +- { +- /* Failure test: No memory allocation after fragmented frame */ +- disable_alloc = 0; +- payload = (char *) (uintptr_t) 0xBAADF00D; +- payload_len = 0x87654321; +- streambuf_read_len = 1000; +- ret = MHD_websocket_decode (ws, +- "\x01\x83\x00\x00\x00\x00" "Hel", +- 9, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (NULL != payload) || +- (0 != payload_len) || +- (9 != streambuf_read_len) || +- (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid ( +- ws))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == payload) +- { +- payload = NULL; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- } +- disable_alloc = 1; +- payload = (char *) (uintptr_t) 0xBAADF00D; +- payload_len = 0x87654321; +- streambuf_read_len = 1000; +- ret = MHD_websocket_decode (ws, +- "\x80\x82\x00\x00\x00\x00" "lo", +- 8, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || +- (NULL != payload) || +- (0 != payload_len) || +- (1000 == streambuf_read_len) || +- (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid ( +- ws))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == payload) +- { +- payload = NULL; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- } +- /* Regular test: Success after memory allocation ok again */ +- /* (streambuf_read_len may not be overwritten for this test) */ +- disable_alloc = 0; +- payload = (char *) (uintptr_t) 0xBAADF00D; +- payload_len = 0x87654321; +- size_t old_streambuf_read_len = streambuf_read_len; +- ret = MHD_websocket_decode (ws, +- "\x80\x82\x00\x00\x00\x00lo" +- + old_streambuf_read_len, +- 8 - old_streambuf_read_len, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_TEXT_FRAME != ret) || +- (NULL == payload) || +- (5 != payload_len) || +- (8 != streambuf_read_len + old_streambuf_read_len) || +- (MHD_WEBSOCKET_VALIDITY_VALID != MHD_websocket_stream_is_valid ( +- ws)) || +- (0 != memcmp ("Hello", payload, 5))) +- { +- fprintf (stderr, +- "Decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == payload) +- { +- payload = NULL; +- } +- if (NULL != payload) +- { +- MHD_websocket_free (ws, payload); +- } +- +- MHD_websocket_stream_free (ws); +- } +- else +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- else +- { +- fprintf (stderr, +- "Memory decode tests failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- +- /* +- ------------------------------------------------------------------------------ +- memory leak test, when freeing while decoding +- ------------------------------------------------------------------------------ +- */ +- { +- disable_alloc = 0; +- struct MHD_WebSocketStream *ws; +- size_t streambuf_read_len = 0; +- char *payload = NULL; +- size_t payload_len = 0; +- int ret = 0; +- +- /* Regular test: Free while decoding of data frame */ +- open_allocs = 0; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | +- MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL)) +- { +- ret = MHD_websocket_decode (ws, +- "\x81\x85\x00\x00\x00\x00Hel", +- 9, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (0 != payload_len) || +- (NULL != payload) || +- (9 != streambuf_read_len) ) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- ret = MHD_websocket_stream_free (ws); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (0 != open_allocs) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u (memory leak detected)\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- else +- { +- fprintf (stderr, +- "Memory test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* Regular test: Free while decoding of control frame */ +- open_allocs = 0; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | +- MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL)) +- { +- ret = MHD_websocket_decode (ws, +- "\x88\x85\x00\x00\x00\x00Hel", +- 9, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (0 != payload_len) || +- (NULL != payload) || +- (9 != streambuf_read_len) ) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- ret = MHD_websocket_stream_free (ws); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (0 != open_allocs) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u (memory leak detected)\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- else +- { +- fprintf (stderr, +- "Memory test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* Regular test: Free while decoding of fragmented data frame */ +- open_allocs = 0; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | +- MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL)) +- { +- ret = MHD_websocket_decode (ws, +- "\x01\x85\x00\x00\x00\x00Hello", +- 11, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (0 != payload_len) || +- (NULL != payload) || +- (11 != streambuf_read_len) ) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- ret = MHD_websocket_stream_free (ws); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (0 != open_allocs) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u (memory leak detected)\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- else +- { +- fprintf (stderr, +- "Memory test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: Free while decoding of continued fragmented data frame */ +- open_allocs = 0; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | +- MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL)) +- { +- ret = MHD_websocket_decode (ws, +- "\x01\x85\x00\x00\x00\x00Hello", +- 11, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (0 != payload_len) || +- (NULL != payload) || +- (11 != streambuf_read_len) ) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- ret = MHD_websocket_decode (ws, +- "\x80\x85\x00\x00\x00\x00Hel", +- 9, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (0 != payload_len) || +- (NULL != payload) || +- (9 != streambuf_read_len) ) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- ret = MHD_websocket_stream_free (ws); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (0 != open_allocs) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u (memory leak detected)\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- else +- { +- fprintf (stderr, +- "Memory test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: Free while decoding of control frame during fragmented data frame */ +- open_allocs = 0; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&ws, +- MHD_WEBSOCKET_FLAG_SERVER +- | +- MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL)) +- { +- ret = MHD_websocket_decode (ws, +- "\x01\x85\x00\x00\x00\x00Hello", +- 11, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (0 != payload_len) || +- (NULL != payload) || +- (11 != streambuf_read_len) ) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- ret = MHD_websocket_decode (ws, +- "\x88\x85\x00\x00\x00\x00Hel", +- 9, +- &streambuf_read_len, +- &payload, +- &payload_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (0 != payload_len) || +- (NULL != payload) || +- (9 != streambuf_read_len) ) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- ret = MHD_websocket_stream_free (ws); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (0 != open_allocs) +- { +- fprintf (stderr, +- "Memory decode test failed in line %u (memory leak detected)\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- else +- { +- fprintf (stderr, +- "Memory test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- +- if (NULL != buf1) +- { +- free (buf1); +- buf1 = NULL; +- } +- if (NULL != buf2) +- { +- free (buf2); +- buf2 = NULL; +- } +- return failed != 0 ? 0x04 : 0x00; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_encode_text()` +- */ +-int +-test_encodes_text () +-{ +- int failed = 0; +- struct MHD_WebSocketStream *wss; +- struct MHD_WebSocketStream *wsc; +- int ret; +- char *buf1 = NULL, *buf2 = NULL; +- char *frame = NULL; +- size_t frame_len = 0; +- int utf8_step = 0; +- +- if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init2 (&wsc, +- MHD_WEBSOCKET_FLAG_CLIENT, +- 0, +- malloc, +- realloc, +- free, +- NULL, +- test_rng)) +- { +- fprintf (stderr, +- "No encode text tests possible due to failed stream init in line %u\n", +- (unsigned int) __LINE__); +- return 0x08; +- } +- if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init (&wss, +- MHD_WEBSOCKET_FLAG_SERVER, +- 0)) +- { +- fprintf (stderr, +- "No encode text tests possible due to failed stream init in line %u\n", +- (unsigned int) __LINE__); +- if (NULL != wsc) +- MHD_websocket_stream_free (wsc); +- return 0x08; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Encoding +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Some data without UTF-8, we are server */ +- ret = MHD_websocket_encode_text (wss, +- "blablabla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x81\x09" "blablabla", 11))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Some data without UTF-8, we are client */ +- ret = MHD_websocket_encode_text (wsc, +- "blablabla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (15 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- "blablabla", +- 9, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Regular test: Some data with UTF-8, we are server */ +- ret = MHD_websocket_encode_text (wss, +- "bla" "\xC3\xA4" "blabla", +- 11, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (13 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x81\x0B" "bla" "\xC3\xA4" "blabla", 13))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Some data with UTF-8, we are client */ +- ret = MHD_websocket_encode_text (wsc, +- "bla" "\xC3\xA4" "blabla", +- 11, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (17 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- "bla" "\xC3\xA4" "blabla", +- 11, +- MHD_WEBSOCKET_STATUS_TEXT_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Edge test (success): Some data with NUL characters, we are server */ +- ret = MHD_websocket_encode_text (wss, +- "bla" "\0\0\0" "bla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x81\x09" "bla" "\0\0\0" "bla", 11))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: Some data with broken UTF-8, we are server */ +- ret = MHD_websocket_encode_text (wss, +- "bla" "\xC3" "blabla", +- 10, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Fragmentation +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Some data without UTF-8 */ +- ret = MHD_websocket_encode_text (wss, +- "blablabla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x81\x09" "blablabla", 11))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: First fragment without UTF-8 */ +- ret = MHD_websocket_encode_text (wss, +- "blablabla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_FIRST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x01\x09" "blablabla", 11))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Middle fragment without UTF-8 */ +- ret = MHD_websocket_encode_text (wss, +- "blablabla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x00\x09" "blablabla", 11))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Last fragment without UTF-8 */ +- ret = MHD_websocket_encode_text (wss, +- "blablabla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x09" "blablabla", 11))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): First fragment with UTF-8 on the edge */ +- ret = MHD_websocket_encode_text (wss, +- "blablabl\xC3", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_FIRST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1 != utf8_step) || +- (0 != memcmp (frame, "\x01\x09" "blablabl\xC3", 11))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Last fragment with UTF-8 on the edge */ +- ret = MHD_websocket_encode_text (wss, +- "\xA4" "blablabla", +- 10, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (12 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x0A" "\xA4" "blablabla", 12))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: Last fragment with UTF-8 on the edge (here with wrong old utf8_step) */ +- utf8_step = MHD_WEBSOCKET_UTF8STEP_NORMAL; +- ret = MHD_websocket_encode_text (wss, +- "\xA4" "blablabla", +- 10, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Last fragment with UTF-8 on the edge for UTF2TAIL_1OF1 */ +- utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1; +- ret = MHD_websocket_encode_text (wss, +- "\xA4" "blablabla", +- 10, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (12 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x0A" "\xA4" "blablabla", 12))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Last fragment with UTF-8 on the edge for UTF3TAIL1_1OF2 */ +- utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL1_1OF2; +- ret = MHD_websocket_encode_text (wss, +- "\xA0\x80" "blablabla", +- 11, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (13 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x0B" "\xA0\x80" "blablabla", 13))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Last fragment with UTF-8 on the edge for UTF3TAIL2_1OF2 */ +- utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL2_1OF2; +- ret = MHD_websocket_encode_text (wss, +- "\x80\x80" "blablabla", +- 11, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (13 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x0B" "\x80\x80" "blablabla", 13))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Last fragment with UTF-8 on the edge for UTF3TAIL_1OF2 */ +- utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_1OF2; +- ret = MHD_websocket_encode_text (wss, +- "\x80\x80" "blablabla", +- 11, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (13 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x0B" "\x80\x80" "blablabla", 13))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Last fragment with UTF-8 on the edge for UTF3TAIL_2OF2 */ +- utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF3TAIL_2OF2; +- ret = MHD_websocket_encode_text (wss, +- "\x80" " blablabla", +- 11, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (13 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x0B" "\x80" " blablabla", 13))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Last fragment with UTF-8 on the edge for UTF4TAIL1_1OF3 */ +- utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL1_1OF3; +- ret = MHD_websocket_encode_text (wss, +- "\x90\x80\x80" "blablabla", +- 12, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (14 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x0C" "\x90\x80\x80" "blablabla", 14))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Last fragment with UTF-8 on the edge for UTF4TAIL2_1OF3 */ +- utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL2_1OF3; +- ret = MHD_websocket_encode_text (wss, +- "\x80\x80\x80" "blablabla", +- 12, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (14 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x0C" "\x80\x80\x80" "blablabla", 14))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Last fragment with UTF-8 on the edge for UTF4TAIL_1OF3 */ +- utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_1OF3; +- ret = MHD_websocket_encode_text (wss, +- "\x80\x80\x80" "blablabla", +- 12, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (14 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x0C" "\x80\x80\x80" "blablabla", 14))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Last fragment with UTF-8 on the edge for UTF4TAIL_2OF3 */ +- utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_2OF3; +- ret = MHD_websocket_encode_text (wss, +- "\x80\x80" " blablabla", +- 12, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (14 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x0C" "\x80\x80" " blablabla", 14))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Last fragment with UTF-8 on the edge for UTF4TAIL_3OF3 */ +- utf8_step = MHD_WEBSOCKET_UTF8STEP_UTF4TAIL_3OF3; +- ret = MHD_websocket_encode_text (wss, +- "\x80" " blablabla", +- 12, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (14 != frame_len) || +- (NULL == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x0C" "\x80" " blablabla", 14))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Length checks +- ------------------------------------------------------------------------------ +- */ +- /* Edge test (success): Text frame without data */ +- ret = MHD_websocket_encode_text (wss, +- NULL, +- 0, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x81\x00", 2))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Text frame with 1 byte of data */ +- ret = MHD_websocket_encode_text (wss, +- "a", +- 1, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (3 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x81\x01" "a", 3))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Text frame with 125 bytes of data */ +- ret = MHD_websocket_encode_text (wss, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 125, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (127 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x81\x7D" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 127))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Text frame with 126 bytes of data */ +- ret = MHD_websocket_encode_text (wss, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", +- 126, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (130 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x81\x7E\x00\x7E" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", +- 130))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Text frame with 65535 bytes of data */ +- allocate_length_test_data (&buf1, +- &buf2, +- 65535, +- "\x81\x7E\xFF\xFF", +- 4); +- ret = MHD_websocket_encode_text (wss, +- buf2, +- 65535, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (65535 + 4 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, buf1, 65535 + 4))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Text frame with 65536 bytes of data */ +- allocate_length_test_data (&buf1, +- &buf2, +- 65536, +- "\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", +- 10); +- ret = MHD_websocket_encode_text (wss, +- buf2, +- 65536, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (65536 + 10 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, buf1, 65536 + 10))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Text frame with 100 MB of data */ +- allocate_length_test_data (&buf1, +- &buf2, +- 104857600, +- "\x81\x7F\x00\x00\x00\x00\x06\x40\x00\x00", +- 10); +- ret = MHD_websocket_encode_text (wss, +- buf2, +- 104857600, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (104857600 + 10 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, buf1, 104857600 + 10))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- if (NULL != buf1) +- { +- free (buf1); +- buf1 = NULL; +- } +- if (NULL != buf2) +- { +- free (buf2); +- buf2 = NULL; +- } +-#ifdef ENABLE_64BIT_TESTS +- /* Fail test: frame_len is greater than 0x7FFFFFFFFFFFFFFF +- (this is the maximum allowed payload size) */ +- frame_len = 0; +- ret = MHD_websocket_encode_text (wss, +- "abc", +- (uint64_t) 0x8000000000000000, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +-#endif +- +- /* +- ------------------------------------------------------------------------------ +- Wrong parameters +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: `ws` not passed */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_text (NULL, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `payload_utf8` not passed, but `payload_utf8_len` != 0 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_text (wss, +- NULL, +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: `payload_utf8` passed, but `payload_utf8_len` == 0 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_text (wss, +- "abc", +- 0, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (((char *) (uintptr_t) 0xBAADF00D) == frame) || +- (0 != memcmp (frame, "\x81\x00", 2))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `frame` not passed */ +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_text (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- NULL, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: `frame_len` not passed */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- ret = MHD_websocket_encode_text (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- NULL, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: `utf8_step` passed for non-fragmentation +- (is allowed and `utf8_step` will be filled then) */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- utf8_step = -99; +- ret = MHD_websocket_encode_text (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (5 != frame_len) || +- (NULL == frame) || +- (((char *) (uintptr_t) 0xBAADF00D) == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x81\x03" "abc", 5))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `utf8_step` passed for non-fragmentation with invalid UTF-8 +- (is allowed and `utf8_step` will be filled then) */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- utf8_step = -99; +- ret = MHD_websocket_encode_text (wss, +- "ab\xC3", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) || +- (MHD_WEBSOCKET_UTF8STEP_UTF2TAIL_1OF1 != utf8_step) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `utf8_step` not passed for fragmentation #1 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_text (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_FIRST, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `utf8_step` not passed for fragmentation #2 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_text (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `utf8_step` not passed for fragmentation #3 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_text (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: `utf8_step` passed for fragmentation #1 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- utf8_step = -99; +- ret = MHD_websocket_encode_text (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_FIRST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (5 != frame_len) || +- (NULL == frame) || +- (((char *) (uintptr_t) 0xBAADF00D) == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x01\x03" "abc", 5))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: `utf8_step` passed for fragmentation #2 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- utf8_step = MHD_WEBSOCKET_UTF8STEP_NORMAL; +- ret = MHD_websocket_encode_text (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (5 != frame_len) || +- (NULL == frame) || +- (((char *) (uintptr_t) 0xBAADF00D) == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x00\x03" "abc", 5))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: `utf8_step` passed for fragmentation #3 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- utf8_step = MHD_WEBSOCKET_UTF8STEP_NORMAL; +- ret = MHD_websocket_encode_text (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (5 != frame_len) || +- (NULL == frame) || +- (((char *) (uintptr_t) 0xBAADF00D) == frame) || +- (MHD_WEBSOCKET_UTF8STEP_NORMAL != utf8_step) || +- (0 != memcmp (frame, "\x80\x03" "abc", 5))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `fragmentation` has an invalid value */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- utf8_step = -99; +- ret = MHD_websocket_encode_text (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_LAST + 1, +- &frame, +- &frame_len, +- &utf8_step); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) || +- (-99 != utf8_step) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- validity after temporary out-of-memory +- ------------------------------------------------------------------------------ +- */ +- { +- struct MHD_WebSocketStream *wsx; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&wsx, +- MHD_WEBSOCKET_FLAG_SERVER, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL)) +- { +- /* Fail test: allocation while no memory available */ +- disable_alloc = 1; +- ret = MHD_websocket_encode_text (wsx, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsx, frame); +- frame = NULL; +- } +- /* Regular test: allocation while memory is available again */ +- disable_alloc = 0; +- ret = MHD_websocket_encode_text (wsx, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (5 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x81\x03" "abc", 5))) +- { +- fprintf (stderr, +- "Encode text test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsx, frame); +- frame = NULL; +- } +- +- MHD_websocket_stream_free (wsx); +- } +- else +- { +- fprintf (stderr, +- "Couldn't perform memory test for text encoding in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- +- if (NULL != buf1) +- free (buf1); +- if (NULL != buf2) +- free (buf2); +- if (NULL != wsc) +- MHD_websocket_stream_free (wsc); +- if (NULL != wss) +- MHD_websocket_stream_free (wss); +- +- return failed != 0 ? 0x08 : 0x00; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_encode_binary()` +- */ +-int +-test_encodes_binary () +-{ +- int failed = 0; +- struct MHD_WebSocketStream *wss; +- struct MHD_WebSocketStream *wsc; +- int ret; +- char *buf1 = NULL, *buf2 = NULL; +- char *frame = NULL; +- size_t frame_len = 0; +- +- if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init2 (&wsc, +- MHD_WEBSOCKET_FLAG_CLIENT, +- 0, +- malloc, +- realloc, +- free, +- NULL, +- test_rng)) +- { +- fprintf (stderr, +- "No encode binary tests possible due to failed stream init in line %u\n", +- (unsigned int) __LINE__); +- return 0x10; +- } +- if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init (&wss, +- MHD_WEBSOCKET_FLAG_SERVER, +- 0)) +- { +- fprintf (stderr, +- "No encode binary tests possible due to failed stream init in line %u\n", +- (unsigned int) __LINE__); +- if (NULL != wsc) +- MHD_websocket_stream_free (wsc); +- return 0x10; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Encoding +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Some data, we are server */ +- ret = MHD_websocket_encode_binary (wss, +- "blablabla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x82\x09" "blablabla", 11))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Some data, we are client */ +- ret = MHD_websocket_encode_binary (wsc, +- "blablabla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (15 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- "blablabla", +- 9, +- MHD_WEBSOCKET_STATUS_BINARY_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Edge test (success): Some data with NUL characters, we are server */ +- ret = MHD_websocket_encode_binary (wss, +- "bla" "\0\0\0" "bla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x82\x09" "bla" "\0\0\0" "bla", 11))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Some data which looks like broken UTF-8, we are server */ +- ret = MHD_websocket_encode_binary (wss, +- "bla" "\xC3" "blabla", +- 10, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (12 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x82\x0A" "bla" "\xC3" "blabla", 12))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Fragmentation +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Some data */ +- ret = MHD_websocket_encode_binary (wss, +- "blablabla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x82\x09" "blablabla", 11))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: First fragment */ +- ret = MHD_websocket_encode_binary (wss, +- "blablabla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_FIRST, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x02\x09" "blablabla", 11))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Middle fragment */ +- ret = MHD_websocket_encode_binary (wss, +- "blablabla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_FOLLOWING, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x00\x09" "blablabla", 11))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Last fragment */ +- ret = MHD_websocket_encode_binary (wss, +- "blablabla", +- 9, +- MHD_WEBSOCKET_FRAGMENTATION_LAST, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x80\x09" "blablabla", 11))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Length checks +- ------------------------------------------------------------------------------ +- */ +- /* Edge test (success): Binary frame without data */ +- ret = MHD_websocket_encode_binary (wss, +- NULL, +- 0, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x82\x00", 2))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Binary frame with 1 byte of data */ +- ret = MHD_websocket_encode_binary (wss, +- "a", +- 1, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (3 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x82\x01" "a", 3))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Binary frame with 125 bytes of data */ +- ret = MHD_websocket_encode_binary (wss, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 125, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (127 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x82\x7D" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 127))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Binary frame with 126 bytes of data */ +- ret = MHD_websocket_encode_binary (wss, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", +- 126, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (130 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x82\x7E\x00\x7E" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", +- 130))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Binary frame with 65535 bytes of data */ +- allocate_length_test_data (&buf1, +- &buf2, +- 65535, +- "\x82\x7E\xFF\xFF", +- 4); +- ret = MHD_websocket_encode_binary (wss, +- buf2, +- 65535, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (65535 + 4 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, buf1, 65535 + 4))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Binary frame with 65536 bytes of data */ +- allocate_length_test_data (&buf1, +- &buf2, +- 65536, +- "\x82\x7F\x00\x00\x00\x00\x00\x01\x00\x00", +- 10); +- ret = MHD_websocket_encode_binary (wss, +- buf2, +- 65536, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (65536 + 10 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, buf1, 65536 + 10))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Binary frame with 100 MB of data */ +- allocate_length_test_data (&buf1, +- &buf2, +- 104857600, +- "\x82\x7F\x00\x00\x00\x00\x06\x40\x00\x00", +- 10); +- ret = MHD_websocket_encode_binary (wss, +- buf2, +- 104857600, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (104857600 + 10 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, buf1, 104857600 + 10))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- if (NULL != buf1) +- { +- free (buf1); +- buf1 = NULL; +- } +- if (NULL != buf2) +- { +- free (buf2); +- buf2 = NULL; +- } +-#ifdef ENABLE_64BIT_TESTS +- /* Fail test: `frame_len` is greater than 0x7FFFFFFFFFFFFFFF +- (this is the maximum allowed payload size) */ +- frame_len = 0; +- ret = MHD_websocket_encode_binary (wss, +- "abc", +- (uint64_t) 0x8000000000000000, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +-#endif +- +- /* +- ------------------------------------------------------------------------------ +- Wrong parameters +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: `ws` not passed */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_binary (NULL, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `payload` not passed, but `payload_len` != 0 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_binary (wss, +- NULL, +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: `payload` passed, but `payload_len` == 0 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_binary (wss, +- "abc", +- 0, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (((char *) (uintptr_t) 0xBAADF00D) == frame) || +- (0 != memcmp (frame, "\x82\x00", 2))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `frame` not passed */ +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_binary (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- NULL, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: `frame_len` not passed */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- ret = MHD_websocket_encode_binary (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `fragmentation` has an invalid value */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_binary (wss, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_LAST + 1, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- validity after temporary out-of-memory +- ------------------------------------------------------------------------------ +- */ +- { +- struct MHD_WebSocketStream *wsx; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&wsx, +- MHD_WEBSOCKET_FLAG_SERVER, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL)) +- { +- /* Fail test: allocation while no memory available */ +- disable_alloc = 1; +- ret = MHD_websocket_encode_binary (wsx, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsx, frame); +- frame = NULL; +- } +- /* Regular test: allocation while memory is available again */ +- disable_alloc = 0; +- ret = MHD_websocket_encode_binary (wsx, +- "abc", +- 3, +- MHD_WEBSOCKET_FRAGMENTATION_NONE, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (5 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x82\x03" "abc", 5))) +- { +- fprintf (stderr, +- "Encode binary test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsx, frame); +- frame = NULL; +- } +- +- MHD_websocket_stream_free (wsx); +- } +- else +- { +- fprintf (stderr, +- "Couldn't perform memory test for binary encoding in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- +- if (NULL != buf1) +- free (buf1); +- if (NULL != buf2) +- free (buf2); +- if (NULL != wsc) +- MHD_websocket_stream_free (wsc); +- if (NULL != wss) +- MHD_websocket_stream_free (wss); +- +- return failed != 0 ? 0x10 : 0x00; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_encode_close()` +- */ +-int +-test_encodes_close () +-{ +- int failed = 0; +- struct MHD_WebSocketStream *wss; +- struct MHD_WebSocketStream *wsc; +- int ret; +- char *buf1 = NULL, *buf2 = NULL; +- char *frame = NULL; +- size_t frame_len = 0; +- +- if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init2 (&wsc, +- MHD_WEBSOCKET_FLAG_CLIENT, +- 0, +- malloc, +- realloc, +- free, +- NULL, +- test_rng)) +- { +- fprintf (stderr, +- "No encode close tests possible due to failed stream init in line %u\n", +- (unsigned int) __LINE__); +- return 0x10; +- } +- if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init2 (&wss, +- MHD_WEBSOCKET_FLAG_SERVER, +- 0, +- malloc, +- realloc, +- free, +- NULL, +- test_rng)) +- { +- fprintf (stderr, +- "No encode close tests possible due to failed stream init in line %u\n", +- (unsigned int) __LINE__); +- if (NULL != wsc) +- MHD_websocket_stream_free (wsc); +- return 0x10; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Encoding +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Some data, we are server */ +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "blablabla", +- 9, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (13 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x88\x0B\x03\xE8" "blablabla", 13))) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Some data, we are client */ +- ret = MHD_websocket_encode_close (wsc, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "blablabla", +- 9, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (17 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- "\x03\xE8" "blablabla", +- 11, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Regular test: Close reason without text, we are server */ +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (4 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x88\x02\x03\xE8", 4))) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Close reason without text, we are client */ +- ret = MHD_websocket_encode_close (wsc, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (8 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- "\x03\xE8", +- 2, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Regular test: Close without reason, we are server */ +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_NO_REASON, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x88\x00", 2))) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Close without reason, we are client */ +- ret = MHD_websocket_encode_close (wsc, +- MHD_WEBSOCKET_CLOSEREASON_NO_REASON, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (6 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Regular test: Close with UTF-8 sequence in reason, we are client */ +- ret = MHD_websocket_encode_close (wsc, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "bla" "\xC3\xA4" "blabla", +- 11, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (19 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- "\x03\xE8" "bla" "\xC3\xA4" "blabla", +- 13, +- MHD_WEBSOCKET_STATUS_CLOSE_FRAME, +- MHD_WEBSOCKET_VALIDITY_ONLY_VALID_FOR_CONTROL_FRAMES, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Edge test (success): Close reason with NUL characters, we are server */ +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_GOING_AWAY, +- "bla" "\0\0\0" "bla", +- 9, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (13 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x88\x0B\x03\xE9" "bla" "\0\0\0" "bla", 13))) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: Some data with broken UTF-8, we are server */ +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "bla" "\xC3" "blabla", +- 10, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_UTF8_ENCODING_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Length checks +- ------------------------------------------------------------------------------ +- */ +- /* Edge test (success): Close frame without payload */ +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_NO_REASON, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x88\x00", 2))) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Close frame only reason code */ +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (4 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x88\x02\x03\xE8", 4))) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Close frame with 1 bytes of reason text */ +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "a", +- 1, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (5 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x88\x03\x03\xE8" "a", 5))) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Close frame with 123 bytes of reason text */ +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456", +- 123, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (127 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x88\x7D\x03\xE8" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456", +- 127))) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (fail): Close frame with 124 bytes of reason text*/ +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567", +- 124, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Wrong parameters +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: `ws` not passed */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_close (NULL, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `payload` not passed, but `payload_len` != 0 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- NULL, +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: `payload` passed, but `payload_len` == 0 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "abc", +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (4 != frame_len) || +- (NULL == frame) || +- (((char *) (uintptr_t) 0xBAADF00D) == frame) || +- (0 != memcmp (frame, "\x88\x02\x03\xE8", 4))) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `frame` not passed */ +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "abc", +- 3, +- NULL, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: `frame_len` not passed */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "abc", +- 3, +- &frame, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: no reason code passed, but reason text */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_close (wss, +- MHD_WEBSOCKET_CLOSEREASON_NO_REASON, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (fail): Invalid reason code */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_close (wss, +- 1, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (fail): Invalid reason code */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_close (wss, +- 999, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Custom reason code */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_close (wss, +- 2000, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (7 != frame_len) || +- (NULL == frame) || +- (((char *) (uintptr_t) 0xBAADF00D) == frame) || +- (0 != memcmp (frame, "\x88\x05\x07\xD0" "abc", 7))) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- validity after temporary out-of-memory +- ------------------------------------------------------------------------------ +- */ +- { +- struct MHD_WebSocketStream *wsx; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&wsx, +- MHD_WEBSOCKET_FLAG_SERVER, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL)) +- { +- /* Fail test: allocation while no memory available */ +- disable_alloc = 1; +- ret = MHD_websocket_encode_close (wsx, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsx, frame); +- frame = NULL; +- } +- /* Regular test: allocation while memory is available again */ +- disable_alloc = 0; +- ret = MHD_websocket_encode_close (wsx, +- MHD_WEBSOCKET_CLOSEREASON_REGULAR, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (7 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x88\x05\x03\xE8" "abc", 7))) +- { +- fprintf (stderr, +- "Encode close test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsx, frame); +- frame = NULL; +- } +- +- MHD_websocket_stream_free (wsx); +- } +- else +- { +- fprintf (stderr, +- "Couldn't perform memory test for close encoding in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- +- if (NULL != buf1) +- free (buf1); +- if (NULL != buf2) +- free (buf2); +- if (NULL != wsc) +- MHD_websocket_stream_free (wsc); +- if (NULL != wss) +- MHD_websocket_stream_free (wss); +- +- return failed != 0 ? 0x20 : 0x00; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_encode_ping()` +- */ +-int +-test_encodes_ping () +-{ +- int failed = 0; +- struct MHD_WebSocketStream *wss; +- struct MHD_WebSocketStream *wsc; +- int ret; +- char *buf1 = NULL, *buf2 = NULL; +- char *frame = NULL; +- size_t frame_len = 0; +- +- if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init2 (&wsc, +- MHD_WEBSOCKET_FLAG_CLIENT, +- 0, +- malloc, +- realloc, +- free, +- NULL, +- test_rng)) +- { +- fprintf (stderr, +- "No encode ping tests possible due to failed stream init in line %u\n", +- (unsigned int) __LINE__); +- return 0x10; +- } +- if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init (&wss, +- MHD_WEBSOCKET_FLAG_SERVER, +- 0)) +- { +- fprintf (stderr, +- "No encode ping tests possible due to failed stream init in line %u\n", +- (unsigned int) __LINE__); +- if (NULL != wsc) +- MHD_websocket_stream_free (wsc); +- return 0x10; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Encoding +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Some data, we are server */ +- ret = MHD_websocket_encode_ping (wss, +- "blablabla", +- 9, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x89\x09" "blablabla", 11))) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Some data, we are client */ +- ret = MHD_websocket_encode_ping (wsc, +- "blablabla", +- 9, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (15 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- "blablabla", +- 9, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Regular test: Ping without payload, we are server */ +- ret = MHD_websocket_encode_ping (wss, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x89\x00", 2))) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Ping without payload, we are client */ +- ret = MHD_websocket_encode_ping (wsc, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (6 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Regular test: Ping with something like UTF-8 sequence in payload, we are client */ +- ret = MHD_websocket_encode_ping (wsc, +- "bla" "\xC3\xA4" "blabla", +- 11, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (17 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- "bla" "\xC3\xA4" "blabla", +- 11, +- MHD_WEBSOCKET_STATUS_PING_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Edge test (success): Ping payload with NUL characters, we are server */ +- ret = MHD_websocket_encode_ping (wss, +- "bla" "\0\0\0" "bla", +- 9, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x89\x09" "bla" "\0\0\0" "bla", 11))) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Ping payload with with something which looks like broken UTF-8, we are server */ +- ret = MHD_websocket_encode_ping (wss, +- "bla" "\xC3" "blabla", +- 10, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (12 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x89\x0A" "bla" "\xC3" "blabla", 12))) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Length checks +- ------------------------------------------------------------------------------ +- */ +- /* Edge test (success): Ping frame without payload */ +- ret = MHD_websocket_encode_ping (wss, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x89\x00", 2))) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Ping frame with one byte of payload */ +- ret = MHD_websocket_encode_ping (wss, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x89\x00", 2))) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Ping frame with 125 bytes of payload */ +- ret = MHD_websocket_encode_ping (wss, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 125, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (127 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x89\x7D" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 127))) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (fail): Ping frame with 126 bytes of payload */ +- ret = MHD_websocket_encode_ping (wss, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", +- 126, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Wrong parameters +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: `ws` not passed */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_ping (NULL, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `payload` not passed, but `payload_len` != 0 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_ping (wss, +- NULL, +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: `payload` passed, but `payload_len` == 0 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_ping (wss, +- "abc", +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (((char *) (uintptr_t) 0xBAADF00D) == frame) || +- (0 != memcmp (frame, "\x89\x00", 2))) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `frame` not passed */ +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_ping (wss, +- "abc", +- 3, +- NULL, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) ) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: `frame_len` not passed */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- ret = MHD_websocket_encode_ping (wss, +- "abc", +- 3, +- &frame, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- validity after temporary out-of-memory +- ------------------------------------------------------------------------------ +- */ +- { +- struct MHD_WebSocketStream *wsx; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&wsx, +- MHD_WEBSOCKET_FLAG_SERVER, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL)) +- { +- /* Fail test: allocation while no memory available */ +- disable_alloc = 1; +- ret = MHD_websocket_encode_ping (wsx, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsx, frame); +- frame = NULL; +- } +- /* Regular test: allocation while memory is available again */ +- disable_alloc = 0; +- ret = MHD_websocket_encode_ping (wsx, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (5 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x89\x03" "abc", 5))) +- { +- fprintf (stderr, +- "Encode ping test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsx, frame); +- frame = NULL; +- } +- +- MHD_websocket_stream_free (wsx); +- } +- else +- { +- fprintf (stderr, +- "Couldn't perform memory test for ping encoding in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- +- if (NULL != buf1) +- free (buf1); +- if (NULL != buf2) +- free (buf2); +- if (NULL != wsc) +- MHD_websocket_stream_free (wsc); +- if (NULL != wss) +- MHD_websocket_stream_free (wss); +- +- return failed != 0 ? 0x40 : 0x00; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_encode_pong()` +- */ +-int +-test_encodes_pong () +-{ +- int failed = 0; +- struct MHD_WebSocketStream *wss; +- struct MHD_WebSocketStream *wsc; +- int ret; +- char *buf1 = NULL, *buf2 = NULL; +- char *frame = NULL; +- size_t frame_len = 0; +- +- if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init2 (&wsc, +- MHD_WEBSOCKET_FLAG_CLIENT, +- 0, +- malloc, +- realloc, +- free, +- NULL, +- test_rng)) +- { +- fprintf (stderr, +- "No encode pong tests possible due to failed stream init in line %u\n", +- (unsigned int) __LINE__); +- return 0x10; +- } +- if (MHD_WEBSOCKET_STATUS_OK != MHD_websocket_stream_init (&wss, +- MHD_WEBSOCKET_FLAG_SERVER, +- 0)) +- { +- fprintf (stderr, +- "No encode pong tests possible due to failed stream init in line %u\n", +- (unsigned int) __LINE__); +- if (NULL != wsc) +- MHD_websocket_stream_free (wsc); +- return 0x10; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Encoding +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Some data, we are server */ +- ret = MHD_websocket_encode_pong (wss, +- "blablabla", +- 9, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x8A\x09" "blablabla", 11))) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Some data, we are client */ +- ret = MHD_websocket_encode_pong (wsc, +- "blablabla", +- 9, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (15 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- "blablabla", +- 9, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Regular test: Pong without payload, we are server */ +- ret = MHD_websocket_encode_pong (wss, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x8A\x00", 2))) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Pong without payload, we are client */ +- ret = MHD_websocket_encode_pong (wsc, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (6 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- NULL, +- 0, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Regular test: Pong with something like UTF-8 sequence in payload, we are client */ +- ret = MHD_websocket_encode_pong (wsc, +- "bla" "\xC3\xA4" "blabla", +- 11, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (17 != frame_len) || +- (NULL == frame) ) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- else +- { +- failed += test_decode_single (__LINE__, +- MHD_WEBSOCKET_FLAG_SERVER +- | MHD_WEBSOCKET_FLAG_NO_FRAGMENTS, +- 0, +- 1, +- 0, +- frame, +- frame_len, +- "bla" "\xC3\xA4" "blabla", +- 11, +- MHD_WEBSOCKET_STATUS_PONG_FRAME, +- MHD_WEBSOCKET_VALIDITY_VALID, +- frame_len); +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsc, frame); +- frame = NULL; +- } +- /* Edge test (success): Pong payload with NUL characters, we are server */ +- ret = MHD_websocket_encode_pong (wss, +- "bla" "\0\0\0" "bla", +- 9, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (11 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x8A\x09" "bla" "\0\0\0" "bla", 11))) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: Pong payload with with something which looks like broken UTF-8, we are server */ +- ret = MHD_websocket_encode_pong (wss, +- "bla" "\xC3" "blabla", +- 10, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (12 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x8A\x0A" "bla" "\xC3" "blabla", 12))) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Length checks +- ------------------------------------------------------------------------------ +- */ +- /* Edge test (success): Pong frame without payload */ +- ret = MHD_websocket_encode_pong (wss, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x8A\x00", 2))) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Pong frame with one byte of payload */ +- ret = MHD_websocket_encode_pong (wss, +- NULL, +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x8A\x00", 2))) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (success): Pong frame with 125 bytes of payload */ +- ret = MHD_websocket_encode_pong (wss, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 125, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (127 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x8A\x7D" +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678", +- 127))) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Edge test (fail): Pong frame with 126 bytes of payload */ +- ret = MHD_websocket_encode_pong (wss, +- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", +- 126, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_MAXIMUM_SIZE_EXCEEDED != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Wrong parameters +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: `ws` not passed */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_pong (NULL, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `payload` not passed, but `payload_len` != 0 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_pong (wss, +- NULL, +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Regular test: `payload` passed, but `payload_len` == 0 */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_pong (wss, +- "abc", +- 0, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (2 != frame_len) || +- (NULL == frame) || +- (((char *) (uintptr_t) 0xBAADF00D) == frame) || +- (0 != memcmp (frame, "\x8A\x00", 2))) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- /* Fail test: `frame` not passed */ +- frame_len = 0x87654321; +- ret = MHD_websocket_encode_pong (wss, +- "abc", +- 3, +- NULL, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (0 != frame_len) ) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: `frame_len` not passed */ +- frame = (char *) (uintptr_t) 0xBAADF00D; +- ret = MHD_websocket_encode_pong (wss, +- "abc", +- 3, +- &frame, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (((char *) (uintptr_t) 0xBAADF00D) == frame) +- { +- frame = NULL; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wss, frame); +- frame = NULL; +- } +- +- /* +- ------------------------------------------------------------------------------ +- validity after temporary out-of-memory +- ------------------------------------------------------------------------------ +- */ +- { +- struct MHD_WebSocketStream *wsx; +- if (MHD_WEBSOCKET_STATUS_OK == MHD_websocket_stream_init2 (&wsx, +- MHD_WEBSOCKET_FLAG_SERVER, +- 0, +- test_malloc, +- test_realloc, +- test_free, +- NULL, +- NULL)) +- { +- /* Fail test: allocation while no memory available */ +- disable_alloc = 1; +- ret = MHD_websocket_encode_pong (wsx, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_MEMORY_ERROR != ret) || +- (0 != frame_len) || +- (NULL != frame) ) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsx, frame); +- frame = NULL; +- } +- /* Regular test: allocation while memory is available again */ +- disable_alloc = 0; +- ret = MHD_websocket_encode_pong (wsx, +- "abc", +- 3, +- &frame, +- &frame_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (5 != frame_len) || +- (NULL == frame) || +- (0 != memcmp (frame, "\x8A\x03" "abc", 5))) +- { +- fprintf (stderr, +- "Encode pong test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- if (NULL != frame) +- { +- MHD_websocket_free (wsx, frame); +- frame = NULL; +- } +- +- MHD_websocket_stream_free (wsx); +- } +- else +- { +- fprintf (stderr, +- "Couldn't perform memory test for pong encoding in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- } +- +- if (NULL != buf1) +- free (buf1); +- if (NULL != buf2) +- free (buf2); +- if (NULL != wsc) +- MHD_websocket_stream_free (wsc); +- if (NULL != wss) +- MHD_websocket_stream_free (wss); +- +- return failed != 0 ? 0x80 : 0x00; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_split_close_reason()` +- */ +-int +-test_split_close_reason () +-{ +- int failed = 0; +- const char *payload; +- unsigned short reason_code; +- const char *reason_utf8; +- size_t reason_utf8_len; +- int ret; +- +- /* +- ------------------------------------------------------------------------------ +- Normal splits +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Reason code + Reason text */ +- reason_code = 9999; +- reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; +- reason_utf8_len = 12345; +- payload = "\x03\xE8" "abc"; +- ret = MHD_websocket_split_close_reason (payload, +- 5, +- &reason_code, +- &reason_utf8, +- &reason_utf8_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (MHD_WEBSOCKET_CLOSEREASON_REGULAR != reason_code) || +- (3 != reason_utf8_len) || +- (payload + 2 != reason_utf8) ) +- { +- fprintf (stderr, +- "split close reason test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: Reason code */ +- reason_code = 9999; +- reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; +- reason_utf8_len = 12345; +- payload = "\x03\xE8"; +- ret = MHD_websocket_split_close_reason (payload, +- 2, +- &reason_code, +- &reason_utf8, +- &reason_utf8_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (MHD_WEBSOCKET_CLOSEREASON_REGULAR != reason_code) || +- (0 != reason_utf8_len) || +- (NULL != reason_utf8) ) +- { +- fprintf (stderr, +- "split close reason test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: No payload */ +- reason_code = 9999; +- reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; +- reason_utf8_len = 12345; +- payload = NULL; +- ret = MHD_websocket_split_close_reason (payload, +- 0, +- &reason_code, +- &reason_utf8, +- &reason_utf8_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (MHD_WEBSOCKET_CLOSEREASON_NO_REASON != reason_code) || +- (0 != reason_utf8_len) || +- (NULL != reason_utf8) ) +- { +- fprintf (stderr, +- "split close reason test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: `payload` is not NULL given, but `payload_len` == 0 */ +- reason_code = 9999; +- reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; +- reason_utf8_len = 12345; +- payload = "abc"; +- ret = MHD_websocket_split_close_reason (payload, +- 0, +- &reason_code, +- &reason_utf8, +- &reason_utf8_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (MHD_WEBSOCKET_CLOSEREASON_NO_REASON != reason_code) || +- (0 != reason_utf8_len) || +- (NULL != reason_utf8) ) +- { +- fprintf (stderr, +- "split close reason test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Wrong parameters +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: `payload` not passed, but `payload_len` != 0 */ +- reason_code = 9999; +- reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; +- reason_utf8_len = 12345; +- payload = NULL; +- ret = MHD_websocket_split_close_reason (payload, +- 3, +- &reason_code, +- &reason_utf8, +- &reason_utf8_len); +- if ((MHD_WEBSOCKET_STATUS_PARAMETER_ERROR != ret) || +- (MHD_WEBSOCKET_CLOSEREASON_NO_REASON != reason_code) || +- (0 != reason_utf8_len) || +- (NULL != reason_utf8) ) +- { +- fprintf (stderr, +- "split close reason test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: `reason_code` not passed */ +- reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; +- reason_utf8_len = 12345; +- payload = "\x03\xE8" "abc"; +- ret = MHD_websocket_split_close_reason (payload, +- 5, +- NULL, +- &reason_utf8, +- &reason_utf8_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (3 != reason_utf8_len) || +- (payload + 2 != reason_utf8) ) +- { +- fprintf (stderr, +- "split close reason test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: `reason_utf8` not passed */ +- reason_code = 9999; +- reason_utf8_len = 12345; +- payload = "\x03\xE8" "abc"; +- ret = MHD_websocket_split_close_reason (payload, +- 5, +- &reason_code, +- NULL, +- &reason_utf8_len); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (MHD_WEBSOCKET_CLOSEREASON_REGULAR != reason_code) || +- (3 != reason_utf8_len) ) +- { +- fprintf (stderr, +- "split close reason test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: `reason_utf8_len` not passed */ +- reason_code = 9999; +- reason_utf8 = (const char *) (intptr_t) 0xBAADF00D; +- payload = "\x03\xE8" "abc"; +- ret = MHD_websocket_split_close_reason (payload, +- 5, +- &reason_code, +- &reason_utf8, +- NULL); +- if ((MHD_WEBSOCKET_STATUS_OK != ret) || +- (MHD_WEBSOCKET_CLOSEREASON_REGULAR != reason_code) || +- (payload + 2 != reason_utf8) ) +- { +- fprintf (stderr, +- "split close reason test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: `reason_code`, `reason_utf8` and `reason_utf8_len` not passed */ +- /* (this is not prohibited, although it doesn't really make sense) */ +- payload = "\x03\xE8" "abc"; +- ret = MHD_websocket_split_close_reason (payload, +- 5, +- NULL, +- NULL, +- NULL); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "split close reason test failed in line %u\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- return failed != 0 ? 0x100 : 0x00; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_check_http_version()` +- */ +-int +-test_check_http_version () +-{ +- int failed = 0; +- int ret; +- +- /* +- ------------------------------------------------------------------------------ +- Version check with valid HTTP version syntax +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: HTTP/1.1 */ +- ret = MHD_websocket_check_http_version ("HTTP/1.1"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: HTTP/1.2 */ +- ret = MHD_websocket_check_http_version ("HTTP/1.2"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: HTTP/1.10 */ +- ret = MHD_websocket_check_http_version ("HTTP/1.10"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: HTTP/2.0 */ +- ret = MHD_websocket_check_http_version ("HTTP/2.0"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: HTTP/3.0 */ +- ret = MHD_websocket_check_http_version ("HTTP/3.0"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: HTTP/1.0 */ +- ret = MHD_websocket_check_http_version ("HTTP/1.0"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: HTTP/0.9 */ +- ret = MHD_websocket_check_http_version ("HTTP/0.9"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Version check edge cases +- ------------------------------------------------------------------------------ +- */ +- /* Edge test (success): HTTP/123.45 */ +- ret = MHD_websocket_check_http_version ("HTTP/123.45"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): HTTP/1.45 */ +- ret = MHD_websocket_check_http_version ("HTTP/1.45"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): HTTP/01.1 */ +- ret = MHD_websocket_check_http_version ("HTTP/01.1"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): HTTP/0001.1 */ +- ret = MHD_websocket_check_http_version ("HTTP/0001.1"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): HTTP/1.01 */ +- ret = MHD_websocket_check_http_version ("HTTP/1.01"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): HTTP/1.0001 */ +- ret = MHD_websocket_check_http_version ("HTTP/1.0001"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): HTTP/0001.0001 */ +- ret = MHD_websocket_check_http_version ("HTTP/0001.0001"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): HTTP/2.000 */ +- ret = MHD_websocket_check_http_version ("HTTP/2.000"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): HTTP/0.0 */ +- ret = MHD_websocket_check_http_version ("HTTP/0.0"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): HTTP/00.0 */ +- ret = MHD_websocket_check_http_version ("HTTP/00.0"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): HTTP/00.0 */ +- ret = MHD_websocket_check_http_version ("HTTP/0.00"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Invalid version syntax +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: (empty string) */ +- ret = MHD_websocket_check_http_version (""); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: http/1.1 */ +- ret = MHD_websocket_check_http_version ("http/1.1"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: "HTTP / 1.1" */ +- ret = MHD_websocket_check_http_version ("HTTP / 1.1"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Missing parameters +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: NULL as version */ +- ret = MHD_websocket_check_http_version (NULL); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_http_version test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- return failed != 0 ? 0x200 : 0x00; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_check_connection_header()` +- */ +-int +-test_check_connection_header () +-{ +- int failed = 0; +- int ret; +- +- /* +- ------------------------------------------------------------------------------ +- Check with valid Connection header syntax +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: Upgrade */ +- ret = MHD_websocket_check_connection_header ("Upgrade"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Regular test: keep-alive, Upgrade */ +- ret = MHD_websocket_check_connection_header ("keep-alive, Upgrade"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: keep-alive */ +- ret = MHD_websocket_check_connection_header ("keep-alive"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: close */ +- ret = MHD_websocket_check_connection_header ("close"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Connection check edge cases +- ------------------------------------------------------------------------------ +- */ +- /* Edge test (success): keep-alive,Upgrade */ +- ret = MHD_websocket_check_connection_header ("keep-alive,Upgrade"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): Upgrade, keep-alive */ +- ret = MHD_websocket_check_connection_header ("Upgrade, keep-alive"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): Upgrade,keep-alive */ +- ret = MHD_websocket_check_connection_header ("Upgrade,keep-alive"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): Transfer-Encoding,Upgrade,keep-alive */ +- ret = MHD_websocket_check_connection_header ( +- "Transfer-Encoding,Upgrade,keep-alive"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): Transfer-Encoding , Upgrade , keep-alive */ +- ret = MHD_websocket_check_connection_header ( +- "Transfer-Encoding , Upgrade , keep-alive"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): upgrade */ +- ret = MHD_websocket_check_connection_header ("upgrade"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): UPGRADE */ +- ret = MHD_websocket_check_connection_header ("UPGRADE"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): All allowed token characters, then upgrade token */ +- ret = MHD_websocket_check_connection_header ( +- "!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,Upgrade"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): Different, allowed whitespaces */ +- ret = MHD_websocket_check_connection_header (" \tUpgrade \t"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): Different, disallowed whitespaces */ +- ret = MHD_websocket_check_connection_header ("\rUpgrade"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): Different, disallowed whitespaces */ +- ret = MHD_websocket_check_connection_header ("\nUpgrade"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): Different, disallowed whitespaces */ +- ret = MHD_websocket_check_connection_header ("\vUpgrade"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): Different, disallowed whitespaces */ +- ret = MHD_websocket_check_connection_header ("\fUpgrade"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Invalid header syntax +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: (empty string) */ +- ret = MHD_websocket_check_connection_header (""); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: (Disallowed) multiple word token with the term "Upgrade" in it */ +- ret = MHD_websocket_check_connection_header ("Upgrade or Downgrade"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: Invalid characters */ +- ret = MHD_websocket_check_connection_header ("\"Upgrade\""); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Missing parameters +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: NULL as connection */ +- ret = MHD_websocket_check_connection_header (NULL); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_connection_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- return failed != 0 ? 0x400 : 0x00; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_check_upgrade_header()` +- */ +-int +-test_check_upgrade_header () +-{ +- int failed = 0; +- int ret; +- +- /* +- ------------------------------------------------------------------------------ +- Check with valid Upgrade header syntax +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: websocket */ +- ret = MHD_websocket_check_upgrade_header ("websocket"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: HTTP/2.0 */ +- ret = MHD_websocket_check_upgrade_header ("HTTP/2.0"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Upgrade check edge cases +- ------------------------------------------------------------------------------ +- */ +- /* Edge test (success): websocket,HTTP/2.0 */ +- ret = MHD_websocket_check_upgrade_header ("websocket,HTTP/2.0"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): websocket ,HTTP/2.0 */ +- ret = MHD_websocket_check_upgrade_header (" websocket ,HTTP/2.0"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): HTTP/2.0, websocket */ +- ret = MHD_websocket_check_upgrade_header ("HTTP/2.0, websocket "); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): websocket/13 */ +- ret = MHD_websocket_check_upgrade_header ("websocket/13"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): WeBsOcKeT */ +- ret = MHD_websocket_check_upgrade_header ("WeBsOcKeT"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): WEBSOCKET */ +- ret = MHD_websocket_check_upgrade_header ("WEBSOCKET"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): All allowed token characters plus /, then websocket keyowrd */ +- ret = MHD_websocket_check_upgrade_header ( +- "!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/,websocket"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (success): Different, allowed whitespaces */ +- ret = MHD_websocket_check_upgrade_header (" \twebsocket \t"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): Different, disallowed whitespaces */ +- ret = MHD_websocket_check_upgrade_header ("\rwebsocket"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): Different, disallowed whitespaces */ +- ret = MHD_websocket_check_upgrade_header ("\nwebsocket"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): Different, disallowed whitespaces */ +- ret = MHD_websocket_check_upgrade_header ("\vwebsocket"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): Different, disallowed whitespaces */ +- ret = MHD_websocket_check_upgrade_header ("\fwebsocket"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Invalid header syntax +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: (empty string) */ +- ret = MHD_websocket_check_upgrade_header (""); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: (Disallowed) multiple word token with the term "websocket" in it */ +- ret = MHD_websocket_check_upgrade_header ("websocket or something"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: Invalid characters */ +- ret = MHD_websocket_check_upgrade_header ("\"websocket\""); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Missing parameters +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: NULL as upgrade */ +- ret = MHD_websocket_check_upgrade_header (NULL); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_upgrade_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- return failed != 0 ? 0x800 : 0x00; +-} +- +- +-/** +- * Test procedure for `MHD_websocket_check_version_header()` +- */ +-int +-test_check_version_header () +-{ +- int failed = 0; +- int ret; +- +- /* +- ------------------------------------------------------------------------------ +- Check with valid Upgrade header syntax +- ------------------------------------------------------------------------------ +- */ +- /* Regular test: 13 */ +- ret = MHD_websocket_check_version_header ("13"); +- if (MHD_WEBSOCKET_STATUS_OK != ret) +- { +- fprintf (stderr, +- "check_version_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Version check edge cases +- ------------------------------------------------------------------------------ +- */ +- /* Edge test (fail): 14 */ +- ret = MHD_websocket_check_version_header ("14"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_version_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): 12 */ +- ret = MHD_websocket_check_version_header ("12"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_version_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): 0 */ +- ret = MHD_websocket_check_version_header ("1"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_version_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): 1 */ +- ret = MHD_websocket_check_version_header ("1"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_version_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): 130 */ +- ret = MHD_websocket_check_version_header ("130"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_version_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Edge test (fail): " 13" */ +- ret = MHD_websocket_check_version_header (" 13"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_version_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Invalid header syntax +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: (empty string) */ +- ret = MHD_websocket_check_version_header (""); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_version_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- /* Fail test: Invalid characters */ +- ret = MHD_websocket_check_version_header ("abc"); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_version_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- /* +- ------------------------------------------------------------------------------ +- Missing parameters +- ------------------------------------------------------------------------------ +- */ +- /* Fail test: NULL as version */ +- ret = MHD_websocket_check_version_header (NULL); +- if (MHD_WEBSOCKET_STATUS_NO_WEBSOCKET_HANDSHAKE_HEADER != ret) +- { +- fprintf (stderr, +- "check_version_header test failed in line %u.\n", +- (unsigned int) __LINE__); +- ++failed; +- } +- +- return failed != 0 ? 0x1000 : 0x00; +-} +- +- +-int +-main (int argc, char *const *argv) +-{ +- unsigned int errorCount = 0; +- (void) argc; (void) argv; /* Unused. Silent compiler warning. */ +- +- /* seed random number generator */ +- srand ((unsigned long) time (NULL)); +- +- /* perform tests */ +- errorCount += test_inits (); +- errorCount += test_accept (); +- errorCount += test_decodes (); +- errorCount += test_encodes_text (); +- errorCount += test_encodes_binary (); +- errorCount += test_encodes_close (); +- errorCount += test_encodes_ping (); +- errorCount += test_encodes_pong (); +- errorCount += test_split_close_reason (); +- errorCount += test_check_http_version (); +- errorCount += test_check_connection_header (); +- errorCount += test_check_upgrade_header (); +- errorCount += test_check_version_header (); +- +- /* output result */ +- if (errorCount != 0) +- fprintf (stderr, "Error (code: %u)\n", errorCount); +- +- return errorCount != 0; /* 0 == pass */ +-} +-- +2.43.0 + diff --git a/SPECS/libmicrohttpd/libmicrohttpd.spec b/SPECS/libmicrohttpd/libmicrohttpd.spec index 08997483a24..a11a3614eb8 100644 --- a/SPECS/libmicrohttpd/libmicrohttpd.spec +++ b/SPECS/libmicrohttpd/libmicrohttpd.spec @@ -2,7 +2,7 @@ Name: libmicrohttpd Vendor: Microsoft Corporation Distribution: Azure Linux Version: 0.9.77 -Release: 3%{?dist} +Release: 4%{?dist} Summary: Lightweight library for embedding a webserver in applications # * COPYING says that some main sources are only under LGPL-2.1-or-later @@ -14,6 +14,7 @@ License: LGPL-2.1-or-later AND (LGPL-2.1-or-later OR GPL-2.0-or-later WIT URL: http://www.gnu.org/software/libmicrohttpd/ Source0: https://ftp.gnu.org/gnu/libmicrohttpd/%{name}-%{version}.tar.gz Patch0: gnutls-utilize-system-crypto-policy.patch +Patch1: CVE-2025-59777.patch BuildRequires: libtool BuildRequires: texinfo @@ -111,6 +112,9 @@ fi %doc html %changelog +* Thu Nov 13 2025 Azure Linux Security Servicing Account - 0.9.77-4 +- Patch for CVE-2025-59777 + * Thu Feb 01 2024 Dan Streetman - 0.9.77-3 - Update to version from Fedora 39. - Next line is present only to avoid tooling failures, and does not indicate the actual package license. diff --git a/SPECS/moby-containerd-cc/CVE-2024-25621.patch b/SPECS/moby-containerd-cc/CVE-2024-25621.patch new file mode 100644 index 00000000000..507949f1875 --- /dev/null +++ b/SPECS/moby-containerd-cc/CVE-2024-25621.patch @@ -0,0 +1,89 @@ +From 0450f046e6942e513d0ebf1ef5c2aff13daa187f Mon Sep 17 00:00:00 2001 +From: Akihiro Suda +Date: Mon, 27 Oct 2025 16:42:59 +0900 +Subject: [PATCH] Fix directory permissions + +- Create /var/lib/containerd with 0o700 (was: 0o711). +- Create config.TempDir with 0o700 (was: 0o711). +- Create /run/containerd/io.containerd.grpc.v1.cri with 0o700 (was: 0o755). +- Create /run/containerd/io.containerd.sandbox.controller.v1.shim with 0o700 (was: 0o711). +- Leave /run/containerd and /run/containerd/io.containerd.runtime.v2.task created with 0o711, + as required by userns-remapped containers. + /run/containerd/io.containerd.runtime.v2.task// is created with: + - 0o700 for non-userns-remapped containers + - 0o710 for userns-remapped containers with the remapped root group as the owner group. + +Signed-off-by: AllSpark +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://github.com/containerd/containerd/commit/0450f046e6942e513d0ebf1ef5c2aff13daa187f.patch + +--- + pkg/cri/cri.go | 8 ++++++++ + runtime/v2/manager.go | 2 ++ + services/server/server.go | 14 ++++++++++++-- + 3 files changed, 22 insertions(+), 2 deletions(-) + +diff --git a/pkg/cri/cri.go b/pkg/cri/cri.go +index aa57313..55db3a2 100644 +--- a/pkg/cri/cri.go ++++ b/pkg/cri/cri.go +@@ -62,6 +62,14 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) { + return nil, fmt.Errorf("invalid plugin config: %w", err) + } + ++ if err := os.MkdirAll(ic.State, 0700); err != nil { ++ return nil, err ++ } ++ // chmod is needed for upgrading from an older release that created the dir with 0755 ++ if err := os.Chmod(ic.State, 0700); err != nil { ++ return nil, err ++ } ++ + c := criconfig.Config{ + PluginConfig: *pluginConfig, + ContainerdRootDir: filepath.Dir(ic.Root), +diff --git a/runtime/v2/manager.go b/runtime/v2/manager.go +index 73e1af7..d48ac8f 100644 +--- a/runtime/v2/manager.go ++++ b/runtime/v2/manager.go +@@ -133,6 +133,8 @@ type ManagerConfig struct { + // NewShimManager creates a manager for v2 shims + func NewShimManager(ctx context.Context, config *ManagerConfig) (*ShimManager, error) { + for _, d := range []string{config.Root, config.State} { ++ // root: the parent of this directory is created as 0700, not 0711. ++ // state: the parent of this directory is created as 0711 too, so as to support userns-remapped containers. + if err := os.MkdirAll(d, 0711); err != nil { + return nil, err + } +diff --git a/services/server/server.go b/services/server/server.go +index 2a548ef..04782bf 100644 +--- a/services/server/server.go ++++ b/services/server/server.go +@@ -76,12 +76,22 @@ func CreateTopLevelDirectories(config *srvconfig.Config) error { + return err + } + +- if err := sys.MkdirAllWithACL(config.State, 0711); err != nil { ++ if err := sys.MkdirAllWithACL(config.Root, 0700); err != nil { ++ return err ++ } ++ // chmod is needed for upgrading from an older release that created the dir with 0o711 ++ if err := os.Chmod(config.Root, 0700); err != nil { + return err + } + ++ // For supporting userns-remapped containers, the state dir cannot be just mkdired with 0o700. ++ // Each of plugins creates a dedicated directory beneath the state dir with appropriate permission bits. + if config.TempDir != "" { +- if err := sys.MkdirAllWithACL(config.TempDir, 0711); err != nil { ++ if err := sys.MkdirAllWithACL(config.TempDir, 0700); err != nil { ++ return err ++ } ++ // chmod is needed for upgrading from an older release that created the dir with 0o711 ++ if err := os.Chmod(config.Root, 0700); err != nil { + return err + } + if runtime.GOOS == "windows" { +-- +2.45.4 + diff --git a/SPECS/moby-containerd-cc/CVE-2025-64329.patch b/SPECS/moby-containerd-cc/CVE-2025-64329.patch new file mode 100644 index 00000000000..9e367f652a7 --- /dev/null +++ b/SPECS/moby-containerd-cc/CVE-2025-64329.patch @@ -0,0 +1,81 @@ +From 155777be3c6c8bb1e5d3c48df543079eed20bed9 Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Mon, 10 Nov 2025 03:04:25 +0000 +Subject: [PATCH] fix(cri): prevent goroutine leak in ContainerIO.Attach by + honoring ctx cancellation and removing writer group entries; plumb context + through attach call + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://github.com/containerd/containerd/commit/c575d1b5f4011f33b32f71ace75367a92b08c750.patch +--- + pkg/cri/io/container_io.go | 14 +++++++++++--- + pkg/cri/sbserver/container_attach.go | 2 +- + pkg/cri/server/container_attach.go | 2 +- + 3 files changed, 13 insertions(+), 5 deletions(-) + +diff --git a/pkg/cri/io/container_io.go b/pkg/cri/io/container_io.go +index 70bc8b7..e158410 100644 +--- a/pkg/cri/io/container_io.go ++++ b/pkg/cri/io/container_io.go +@@ -17,6 +17,7 @@ + package io + + import ( ++ "context" + "errors" + "io" + "strings" +@@ -134,7 +135,7 @@ func (c *ContainerIO) Pipe() { + + // Attach attaches container stdio. + // TODO(random-liu): Use pools.Copy in docker to reduce memory usage? +-func (c *ContainerIO) Attach(opts AttachOptions) { ++func (c *ContainerIO) Attach(ctx context.Context, opts AttachOptions) { + var wg sync.WaitGroup + key := util.GenerateID() + stdinKey := streamKey(c.id, "attach-"+key, Stdin) +@@ -175,8 +176,15 @@ func (c *ContainerIO) Attach(opts AttachOptions) { + } + + attachStream := func(key string, close <-chan struct{}) { +- <-close +- logrus.Infof("Attach stream %q closed", key) ++ select { ++ case <-close: ++ logrus.Infof("Attach stream %q closed", key) ++ case <-ctx.Done(): ++ logrus.Infof("Attach client of %q cancelled", key) ++ // Avoid writeGroup heap up ++ c.stdoutGroup.Remove(key) ++ c.stderrGroup.Remove(key) ++ } + // Make sure stdin gets closed. + if stdinStreamRC != nil { + stdinStreamRC.Close() +diff --git a/pkg/cri/sbserver/container_attach.go b/pkg/cri/sbserver/container_attach.go +index 56f69c6..b2a534a 100644 +--- a/pkg/cri/sbserver/container_attach.go ++++ b/pkg/cri/sbserver/container_attach.go +@@ -79,6 +79,6 @@ func (c *criService) attachContainer(ctx context.Context, id string, stdin io.Re + }, + } + // TODO(random-liu): Figure out whether we need to support historical output. +- cntr.IO.Attach(opts) ++ cntr.IO.Attach(ctx, opts) + return nil + } +diff --git a/pkg/cri/server/container_attach.go b/pkg/cri/server/container_attach.go +index cd79f3b..aa6519a 100644 +--- a/pkg/cri/server/container_attach.go ++++ b/pkg/cri/server/container_attach.go +@@ -79,6 +79,6 @@ func (c *criService) attachContainer(ctx context.Context, id string, stdin io.Re + }, + } + // TODO(random-liu): Figure out whether we need to support historical output. +- cntr.IO.Attach(opts) ++ cntr.IO.Attach(ctx, opts) + return nil + } +-- +2.45.4 + diff --git a/SPECS/moby-containerd-cc/moby-containerd-cc.spec b/SPECS/moby-containerd-cc/moby-containerd-cc.spec index 0a70fd57d48..17ff81af4c1 100644 --- a/SPECS/moby-containerd-cc/moby-containerd-cc.spec +++ b/SPECS/moby-containerd-cc/moby-containerd-cc.spec @@ -6,7 +6,7 @@ Summary: Industry-standard container runtime for confidential containers Name: moby-%{upstream_name} Version: 1.7.7 -Release: 9%{?dist} +Release: 10%{?dist} License: ASL 2.0 Group: Tools/Container URL: https://www.containerd.io @@ -25,6 +25,8 @@ Patch5: CVE-2023-45288.patch Patch7: CVE-2023-44487.patch Patch8: CVE-2025-27144.patch Patch9: CVE-2024-40635.patch +Patch10:CVE-2024-25621.patch +Patch11:CVE-2025-64329.patch %{?systemd_requires} @@ -82,6 +84,9 @@ fi %config(noreplace) %{_sysconfdir}/containerd/config.toml %changelog +* Mon Nov 10 2025 Azure Linux Security Servicing Account - 1.7.7-10 +- Patch for CVE-2025-64329, CVE-2024-25621 + * Wed Apr 16 2025 Manuel Huber - 1.7.7-9 - Fix CVE-2024-40635 diff --git a/SPECS/nodejs/CVE-2025-5222.patch b/SPECS/nodejs/CVE-2025-5222.patch new file mode 100644 index 00000000000..73e82d48541 --- /dev/null +++ b/SPECS/nodejs/CVE-2025-5222.patch @@ -0,0 +1,164 @@ +From 87e1ef3c27772750cf717253738886a1c04b7b29 Mon Sep 17 00:00:00 2001 +From: Frank Tang +Date: Wed, 22 Jan 2025 11:50:59 -0800 +Subject: [PATCH] ICU-22973 Fix buffer overflow by using CharString + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: https://github.com/unicode-org/icu/commit/2c667e31cfd0b6bb1923627a932fd3453a5bac77.patch +--- + deps/icu-small/source/tools/genrb/parse.cpp | 49 ++++++++++++--------- + 1 file changed, 29 insertions(+), 20 deletions(-) + +diff --git a/deps/icu-small/source/tools/genrb/parse.cpp b/deps/icu-small/source/tools/genrb/parse.cpp +index a6c59948..799a2241 100644 +--- a/deps/icu-small/source/tools/genrb/parse.cpp ++++ b/deps/icu-small/source/tools/genrb/parse.cpp +@@ -1153,7 +1153,7 @@ addCollation(ParseState* state, TableResource *result, const char *collationTyp + struct UString *tokenValue; + struct UString comment; + enum ETokenType token; +- char subtag[1024]; ++ CharString subtag; + UnicodeString rules; + UBool haveRules = false; + UVersionInfo version; +@@ -1189,15 +1189,15 @@ addCollation(ParseState* state, TableResource *result, const char *collationTyp + return nullptr; + } + +- u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1); +- ++ subtag.clear(); ++ subtag.appendInvariantChars(tokenValue->fChars, u_strlen(tokenValue->fChars), *status); + if (U_FAILURE(*status)) + { + res_close(result); + return nullptr; + } + +- member = parseResource(state, subtag, nullptr, status); ++ member = parseResource(state, subtag.data(), nullptr, status); + + if (U_FAILURE(*status)) + { +@@ -1208,7 +1208,7 @@ addCollation(ParseState* state, TableResource *result, const char *collationTyp + { + // Ignore the parsed resources, continue parsing. + } +- else if (uprv_strcmp(subtag, "Version") == 0 && member->isString()) ++ else if (uprv_strcmp(subtag.data(), "Version") == 0 && member->isString()) + { + StringResource *sr = static_cast(member); + char ver[40]; +@@ -1225,11 +1225,11 @@ addCollation(ParseState* state, TableResource *result, const char *collationTyp + result->add(member, line, *status); + member = nullptr; + } +- else if(uprv_strcmp(subtag, "%%CollationBin")==0) ++ else if(uprv_strcmp(subtag.data(), "%%CollationBin")==0) + { + /* discard duplicate %%CollationBin if any*/ + } +- else if (uprv_strcmp(subtag, "Sequence") == 0 && member->isString()) ++ else if (uprv_strcmp(subtag.data(), "Sequence") == 0 && member->isString()) + { + StringResource *sr = static_cast(member); + rules = sr->fString; +@@ -1395,7 +1395,7 @@ parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool n + struct UString *tokenValue; + struct UString comment; + enum ETokenType token; +- char subtag[1024], typeKeyword[1024]; ++ CharString subtag, typeKeyword; + uint32_t line; + + result = table_open(state->bundle, tag, nullptr, status); +@@ -1437,7 +1437,8 @@ parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool n + return nullptr; + } + +- u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1); ++ subtag.clear(); ++ subtag.appendInvariantChars(tokenValue->fChars, u_strlen(tokenValue->fChars), *status); + + if (U_FAILURE(*status)) + { +@@ -1445,9 +1446,9 @@ parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool n + return nullptr; + } + +- if (uprv_strcmp(subtag, "default") == 0) ++ if (uprv_strcmp(subtag.data(), "default") == 0) + { +- member = parseResource(state, subtag, nullptr, status); ++ member = parseResource(state, subtag.data(), nullptr, status); + + if (U_FAILURE(*status)) + { +@@ -1466,22 +1467,29 @@ parseCollationElements(ParseState* state, char *tag, uint32_t startline, UBool n + if(token == TOK_OPEN_BRACE) { + token = getToken(state, &tokenValue, &comment, &line, status); + TableResource *collationRes; +- if (keepCollationType(subtag)) { +- collationRes = table_open(state->bundle, subtag, nullptr, status); ++ if (keepCollationType(subtag.data())) { ++ collationRes = table_open(state->bundle, subtag.data(), nullptr, status); + } else { + collationRes = nullptr; + } + // need to parse the collation data regardless +- collationRes = addCollation(state, collationRes, subtag, startline, status); ++ collationRes = addCollation(state, collationRes, subtag.data(), startline, status); + if (collationRes != nullptr) { + result->add(collationRes, startline, *status); + } + } else if(token == TOK_COLON) { /* right now, we'll just try to see if we have aliases */ + /* we could have a table too */ + token = peekToken(state, 1, &tokenValue, &line, &comment, status); +- u_UCharsToChars(tokenValue->fChars, typeKeyword, u_strlen(tokenValue->fChars) + 1); +- if(uprv_strcmp(typeKeyword, "alias") == 0) { +- member = parseResource(state, subtag, nullptr, status); ++ typeKeyword.clear(); ++ typeKeyword.appendInvariantChars(tokenValue->fChars, u_strlen(tokenValue->fChars), *status); ++ if (U_FAILURE(*status)) ++ { ++ res_close(result); ++ return nullptr; ++ } ++ ++ if(uprv_strcmp(typeKeyword.data(), "alias") == 0) { ++ member = parseResource(state, subtag.data(), nullptr, status); + if (U_FAILURE(*status)) + { + res_close(result); +@@ -1523,7 +1531,7 @@ realParseTable(ParseState* state, TableResource *table, char *tag, uint32_t star + struct UString *tokenValue=nullptr; + struct UString comment; + enum ETokenType token; +- char subtag[1024]; ++ CharString subtag; + uint32_t line; + UBool readToken = false; + +@@ -1562,7 +1570,8 @@ realParseTable(ParseState* state, TableResource *table, char *tag, uint32_t star + } + + if(uprv_isInvariantUString(tokenValue->fChars, -1)) { +- u_UCharsToChars(tokenValue->fChars, subtag, u_strlen(tokenValue->fChars) + 1); ++ subtag.clear(); ++ subtag.appendInvariantChars(tokenValue->fChars, u_strlen(tokenValue->fChars), *status); + } else { + *status = U_INVALID_FORMAT_ERROR; + error(line, "invariant characters required for table keys"); +@@ -1575,7 +1584,7 @@ realParseTable(ParseState* state, TableResource *table, char *tag, uint32_t star + return nullptr; + } + +- member = parseResource(state, subtag, &comment, status); ++ member = parseResource(state, subtag.data(), &comment, status); + + if (member == nullptr || U_FAILURE(*status)) + { +-- +2.45.4 + diff --git a/SPECS/nodejs/nodejs.spec b/SPECS/nodejs/nodejs.spec index 2b28b31fe85..6b80ae56ff7 100644 --- a/SPECS/nodejs/nodejs.spec +++ b/SPECS/nodejs/nodejs.spec @@ -5,7 +5,7 @@ Name: nodejs # WARNINGS: MUST check and update the 'npm_version' macro for every version update of this package. # The version of NPM can be found inside the sources under 'deps/npm/package.json'. Version: 20.14.0 -Release: 9%{?dist} +Release: 10%{?dist} License: BSD AND MIT AND Public Domain AND NAIST-2003 AND Artistic-2.0 Vendor: Microsoft Corporation Distribution: Azure Linux @@ -29,6 +29,7 @@ Patch10: CVE-2025-27516.patch Patch11: CVE-2025-47279.patch Patch12: CVE-2025-23165.patch Patch13: CVE-2025-23166.patch +Patch14: CVE-2025-5222.patch BuildRequires: brotli-devel BuildRequires: c-ares-devel BuildRequires: coreutils >= 8.22 @@ -140,6 +141,9 @@ make cctest %{_prefix}/lib/node_modules/* %changelog +* Fri Nov 07 2025 Azure Linux Security Servicing Account - 20.14.0-10 +- Patch for CVE-2025-5222 + * Tue May 27 2025 Aninda Pradhan - 20.14.0-9 - Patch CVE-2025-23165, CVE-2025-23166 diff --git a/SPECS/packer/CVE-2025-47913.patch b/SPECS/packer/CVE-2025-47913.patch new file mode 100644 index 00000000000..388cf59cea0 --- /dev/null +++ b/SPECS/packer/CVE-2025-47913.patch @@ -0,0 +1,55 @@ +From 559e062ce8bfd6a39925294620b50906ca2a6f95 Mon Sep 17 00:00:00 2001 +From: Nicola Murino +Date: Sun, 31 Aug 2025 20:07:32 +0200 +Subject: [PATCH] ssh/agent: return an error for unexpected message types + +Previously, receiving an unexpected message type in response to a key +listing or a signing request could cause a panic due to a failed type +assertion. + +This change adds a default case to the type switch in order to detect +and explicitly handle unknown or invalid message types, returning a +descriptive error instead of crashing. + +Fixes golang/go#75178 + +Change-Id: Icbc3432adc79fe3c56b1ff23c6724d7a6f710f3a +Reviewed-on: https://go-review.googlesource.com/c/crypto/+/700295 +Reviewed-by: Roland Shoemaker +LUCI-TryBot-Result: Go LUCI +Reviewed-by: Michael Pratt +Reviewed-by: Jakub Ciolek +Upstream patch Reference: https://github.com/golang/crypto/commit/559e062ce8bfd6a39925294620b50906ca2a6f95.patch +--- + vendor/golang.org/x/crypto/ssh/agent/client.go | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go +index 106708d..31bd7e8 100644 +--- a/vendor/golang.org/x/crypto/ssh/agent/client.go ++++ b/vendor/golang.org/x/crypto/ssh/agent/client.go +@@ -430,8 +430,9 @@ func (c *client) List() ([]*Key, error) { + return keys, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to list keys") ++ default: ++ return nil, fmt.Errorf("agent: failed to list keys, unexpected message type %T", msg) + } +- panic("unreachable") + } + + // Sign has the agent sign the data using a protocol 2 key as defined +@@ -462,8 +463,9 @@ func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFl + return &sig, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to sign challenge") ++ default: ++ return nil, fmt.Errorf("agent: failed to list keys, unexpected message type %T", msg) + } +- panic("unreachable") + } + + // unmarshal parses an agent message in packet, returning the parsed +-- +2.45.4 + diff --git a/SPECS/packer/packer.spec b/SPECS/packer/packer.spec index 10d6c692dce..bdbe76d9627 100644 --- a/SPECS/packer/packer.spec +++ b/SPECS/packer/packer.spec @@ -4,7 +4,7 @@ Summary: Tool for creating identical machine images for multiple platforms from a single source configuration. Name: packer Version: 1.9.5 -Release: 10%{?dist} +Release: 11%{?dist} License: MPLv2.0 Vendor: Microsoft Corporation Distribution: Azure Linux @@ -44,6 +44,7 @@ Patch9: CVE-2025-22870.patch Patch10: CVE-2024-51744.patch Patch11: CVE-2025-22872.patch Patch12: CVE-2025-58058.patch +Patch13: CVE-2025-47913.patch BuildRequires: golang >= 1.21 BuildRequires: kernel-headers @@ -75,6 +76,9 @@ go test -mod=vendor %{_bindir}/packer %changelog +* Tue Nov 18 2025 Archana Shettigar - 1.9.5-11 +- Patch CVE-2025-47913 + * Wed Sep 03 2025 Azure Linux Security Servicing Account - 1.9.5-10 - Patch for CVE-2025-58058 diff --git a/SPECS/telegraf/CVE-2025-47913.patch b/SPECS/telegraf/CVE-2025-47913.patch new file mode 100644 index 00000000000..968cdb6ceea --- /dev/null +++ b/SPECS/telegraf/CVE-2025-47913.patch @@ -0,0 +1,50 @@ +From bfcec8590886ef05b312d567b7079be006ed23c2 Mon Sep 17 00:00:00 2001 +From: AllSpark +Date: Tue, 18 Nov 2025 16:24:10 +0000 +Subject: [PATCH] ssh/agent: return an error for unexpected message types + +Previously, receiving an unexpected message type in response to a key +listing or a signing request could cause a panic due to a failed type +assertion. + +This change adds a default case to the type switch in order to detect +and explicitly handle unknown or invalid message types, returning a +descriptive error instead of crashing. + +Fixes golang/go#75178 + +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: AI Backport of https://github.com/golang/crypto/commit/559e062ce8bfd6a39925294620b50906ca2a6f95.patch +--- + vendor/golang.org/x/crypto/ssh/agent/client.go | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/vendor/golang.org/x/crypto/ssh/agent/client.go b/vendor/golang.org/x/crypto/ssh/agent/client.go +index fecba8eb..6dc73e09 100644 +--- a/vendor/golang.org/x/crypto/ssh/agent/client.go ++++ b/vendor/golang.org/x/crypto/ssh/agent/client.go +@@ -430,8 +430,9 @@ func (c *client) List() ([]*Key, error) { + return keys, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to list keys") ++ default: ++ return nil, fmt.Errorf("agent: failed to list keys, unexpected message type %T", msg) + } +- panic("unreachable") + } + + // Sign has the agent sign the data using a protocol 2 key as defined +@@ -462,8 +463,9 @@ func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFl + return &sig, nil + case *failureAgentMsg: + return nil, errors.New("agent: failed to sign challenge") ++ default: ++ return nil, fmt.Errorf("agent: failed to sign challenge, unexpected message type %T", msg) + } +- panic("unreachable") + } + + // unmarshal parses an agent message in packet, returning the parsed +-- +2.45.4 + diff --git a/SPECS/telegraf/telegraf.spec b/SPECS/telegraf/telegraf.spec index 4af7ea5e0b2..a2bce2cf342 100644 --- a/SPECS/telegraf/telegraf.spec +++ b/SPECS/telegraf/telegraf.spec @@ -1,7 +1,7 @@ Summary: agent for collecting, processing, aggregating, and writing metrics. Name: telegraf Version: 1.31.0 -Release: 10%{?dist} +Release: 11%{?dist} License: MIT Vendor: Microsoft Corporation Distribution: Azure Linux @@ -23,6 +23,7 @@ Patch8: CVE-2025-30204.patch Patch9: CVE-2025-27144.patch Patch10: CVE-2025-30215.patch Patch11: CVE-2025-22872.patch +Patch12: CVE-2025-47913.patch BuildRequires: golang BuildRequires: systemd-devel @@ -87,6 +88,9 @@ fi %dir %{_sysconfdir}/%{name}/telegraf.d %changelog +* Tue Nov 18 2025 Azure Linux Security Servicing Account - 1.31.0-11 +- Patch for CVE-2025-47913 + * Tue Apr 22 2025 Mayank Singh - 1.31.0-10 - Fix CVE-2025-22872 with an upstream patch