1
0
Fork 0
mirror of https://libwebsockets.org/repo/libwebsockets synced 2025-05-03 23:49:53 +00:00

Compare commits

...

57 commits

Author SHA1 Message Date
Andy Green
e7fbdac391 lws_mux_mark_immortal: remove noisy log 2025-02-25 19:38:02 +00:00
Mark Adler
bd57dbc241 win32port: zlib: upstream bugfix patch on inftrees.c
From 6a043145ca6e9c55184013841a67b2fef87e44c0 Mon Sep 17 00:00:00 2001
Subject: [PATCH] Remove offset pointer optimization in inftrees.c.

inftrees.c was subtracting an offset from a pointer to an array,
in order to provide a pointer that allowed indexing starting at
the offset. This is not compliant with the C standard, for which
the behavior of a pointer decremented before its allocated memory
is undefined. Per the recommendation of a security audit of the
zlib code by Trail of Bits and TrustInSoft, in support of the
Mozilla Foundation, this tiny optimization was removed, in order
to avoid the possibility of undefined behavior.
2025-02-24 12:52:53 +00:00
Andy Green
df9f518e97 dos2unix: win32port/zlib/inftrees.c 2025-02-24 12:52:43 +00:00
Andy Green
5d1947474e lws_tls_openssl_asn1time_to_unix: fix 13 char asn1 epoch
Also align to struct tm's year epoch of 1900

https://github.com/warmcat/libwebsockets/issues/3341
2025-02-24 12:52:33 +00:00
Andy Green
7333fcc9cd coverity 472861: http2: deal with zero length data without overflow 2025-01-19 16:59:34 +00:00
Andy Green
ff0e0f3c35 coverity 472860: ops-h2: let coverity see all err enums covered
x
2025-01-19 16:59:25 +00:00
Andy Green
b81b24d10e coverity 472863: cookies: length check order wrong 2025-01-19 16:59:17 +00:00
Andy Green
5a34404b1a coverity 872858: hash gen overflow false positive
Help it ignore that we use the MS 7 bits in the next part of the operation
and discard it in the first part.
2025-01-19 16:58:57 +00:00
Andy Green
fce734f279 coverity 472862: cookiejar overflow 2025-01-19 16:58:46 +00:00
Davidovory03
e5506ade69 mbedtls: translate error codes for caller
https://github.com/warmcat/libwebsockets/issues/3315
2025-01-19 16:57:24 +00:00
Albert Ribes
c6e9792188 lejp: E implies float
Since eg, 1e-3 is a float without needing a decimal point, let's just
    generally take it that anything with the exponent token is a float, ie, 1e3
    is also a float despite it can be expressed as an integer.

    This seems right also because E is itself not valid in an integer.

    https://github.com/warmcat/libwebsockets/issues/3308
2025-01-10 14:14:49 +00:00
Andy Green
dc65edd519 spa: use sized local info rather than incoming
We allow a default 0 length in the incoming const info to mean a default
size (of 512).  We implement it by copying the incoming const info to a
copy in the spa that we can adapt, which is all good.

But in two cases after we dumbly use the incoming const info directly
instead of the adapted copy.

https://github.com/warmcat/libwebsockets/issues/3294
2024-12-13 09:23:07 +00:00
level 6
12e52ae293 test-server-extpoll: remove LWS_WITH_EXTERNAL_POLL redefine 2024-12-06 07:43:59 +00:00
Orgad Shaneh
c4b1e34a50 clean: var unused when no logs 2024-11-16 09:08:31 +00:00
Lucas
a71a62f51b mbedtls: fix issue about memory leak
https://github.com/warmcat/libwebsockets/issues/3177
2024-11-08 07:58:59 +00:00
Orgad Shaneh
5102a5c8d6 tls-sessions: Pass correct type for printf %u 2024-10-06 08:11:58 +01:00
Orgad Shaneh
8ad16af9a3 win: simplify error logging in windows-sockets.c 2024-10-03 05:27:54 +01:00
Orgad Shaneh
0ee1984c5c win: change uid_t and gid_t from int to unsigned int
Like they are on Linux.
2024-10-03 05:25:29 +01:00
Orgad Shaneh
dcf9dcaf2a unix-file: Fix signed/unsigned implicit conversion 2024-10-03 05:21:50 +01:00
Orgad Shaneh
a544db3020 win32: zlib: Fix buffer overflow on inflate (CVE-2022-37434) 2024-10-03 05:14:30 +01:00
Andy Green
a1ee5a2c50 mbedtls: provide declaration if ge 3.5
https://github.com/warmcat/libwebsockets/issues/3169
2024-09-29 11:50:41 +01:00
Andy Green
e24114fed9 win: file: use INVALID_HANDLE_VALUE directly
c571d22dba (commitcomment-142753910)
2024-09-25 12:24:35 +01:00
Andy Green
0981808868 doc: session tickets
https://github.com/warmcat/libwebsockets/issues/3226
2024-09-25 12:18:06 +01:00
Andy Green
bad1866c8a wolfssl: have docs follow switch change
https://github.com/warmcat/libwebsockets/issues/3116
2024-09-25 10:35:53 +01:00
Andy Green
d1722af79b check func munging
https://github.com/warmcat/libwebsockets/issues/3181
2024-09-25 09:44:18 +01:00
Andy Green
f7aeadeb0e win: trigger context destroy if pt destroying itself
https://github.com/warmcat/libwebsockets/issues/3182

This follows the flow for *nix
2024-09-25 09:37:03 +01:00
Andy Green
8fc7596fec event: blow error if runtime context options want eventlib we dont have
https://github.com/warmcat/libwebsockets/issues/3186
2024-09-25 09:03:36 +01:00
Andy Green
2ca5d8605b ws: increase sanity check for spins needed to consume buffer to 100
https://github.com/warmcat/libwebsockets/issues/3184
2024-09-25 08:53:41 +01:00
Andy Green
b05e95ec87 pipe: only pt destroy pipe close should close pipe fds
https://github.com/warmcat/libwebsockets/issues/2873
2024-09-25 08:38:44 +01:00
Andy Green
82c97d4022 lws_extension_callback_pm_deflate: make visible
https://github.com/warmcat/libwebsockets/issues/3178
2024-09-25 07:46:35 +01:00
Andy Green
86819f05af win32: upscale timeout_ms to 64-bit int
This may help with this:

https://github.com/warmcat/libwebsockets/issues/3201
2024-09-25 07:11:29 +01:00
Andy Green
51c47daea3 without-server: adapt loops to not touch listen_list
https://github.com/warmcat/libwebsockets/issues/3203
2024-09-25 07:03:54 +01:00
Andy Green
3976131e35 unix-sockets: extra care around short for some toolchains
https://github.com/warmcat/libwebsockets/issues/3163
2024-09-25 06:38:09 +01:00
Andy Green
57a0c16aeb openbsd: disable HIGH_RELIABLITY socket option
https://github.com/warmcat/libwebsockets/issues/3204
2024-09-25 06:32:13 +01:00
Andy Green
154bf55441 openssl: allow custom SSL_CTX with GLOBAL_INIT unset 2024-09-23 13:10:30 +01:00
Andy Green
8c8a2a5be3 lws_map: remove typedef for some toolchains
This backports a change that has been in main for a while
2024-09-23 11:06:36 +01:00
ribes96
7467274d4d cgi: setenv: remove equals from arg
https://github.com/warmcat/libwebsockets/issues/3222
2024-09-23 10:39:23 +01:00
James Darpinian
b462ccd7dd ACME: fixes
Increase polling time and poll the "order" endpoint instead of the "finalize" endpoint. These changes are required for ACME to work with Let's Encrypt as of 2024.
2024-06-24 14:58:35 +01:00
zzblydia
ca375a4cab client hs: fix segmentation fault
https://github.com/warmcat/libwebsockets/pull/3171
2024-06-24 09:09:00 +01:00
streltsovdd
c571d22dba windows: fix check of result of CreateFileW 2024-06-04 06:06:51 +01:00
Seo Suchan
c90a77f124 mbedtls: fix compile on mbedtls ge 3.6 2024-05-07 13:48:09 +01:00
payne.ye
bd8f69e438 smp: extend client to work with tsi
and take care of zombie sul previously left on connect failure path
2024-04-12 06:25:21 +01:00
p-luke
eac4489237 netlink: when binding the per-context socket, let the kernel choose the unicast address.
When using multiple client contextes in a single application, rops_pt_init_destroy_netlink() fails binding the second socket and on - only the first one succeeds. The failure is made obvious by this log:
  W: rops_pt_init_destroy_netlink: netlink bind failed

So, let's fix this by doing what netlink(7) man page suggests:
  If the application sets nl_pid before calling bind(2), then it is up to the
  application to make sure that nl_pid is unique. If the application sets it
  to 0, the kernel takes care of assigning it. The kernel assigns the process
  ID to the first netlink socket the process opens and assigns a unique nl_pid
  to every netlink socket that the process subsequently creates.
2024-03-20 07:29:48 +00:00
Andy Green
0a132164c2 h2: cleanly return if fd is -1 on custom close 2024-03-08 06:44:22 +00:00
Liu DongMiao
6901c32a9d raw-skt: don't read more than rx_buffer_size
When other roles like ws reading data, they follow `rx_buffer_size`, then fallback to context's `pt_serv_buf_size`.
However, `raw-skt` don't follow `rx_buffer_size`, always use 0, then fallback to `pt_serv_buf_size`.

This PR make `raw-skt` don't read more than `rx_buffer_size` data.
2024-03-07 09:50:47 +00:00
Liu Dongmiao
130a446b90 wolfssl: fix build 2024-03-07 09:50:41 +00:00
Liu DongMiao
893ff81a8d raw: connect callback can be triggered twice 2024-03-07 09:50:33 +00:00
Lio DongMiao
0fd97f652a context: fall back if no build-time mbedtls version 2024-03-07 09:50:26 +00:00
Patrick Johnston
50375030a3 genaes: fix lws_genaes_create comment 2024-03-06 13:10:18 +00:00
Andy Green
cd3869e8b9 certinfo: fix unused var with NO_LOGS 2024-03-01 09:17:53 +00:00
Dustin Lundquist
ab683ca6a6 ev: remove any watchers on close 2024-01-15 09:30:25 +00:00
DomB
881a0ac34a lecp: fix format_scan function for numeric longer than 2 digits and negative numbers 2024-01-08 09:18:32 +00:00
Philippe Ombredanne
be473054bd License: Fix typo in MIT text in fsmount.c
Somehow, a string replacement of ns by fsm had damaged
the license text and introduced garbage.

Signed-off-by: Philippe Ombredanne <pombredanne@nexb.com>
2023-11-27 09:45:01 +00:00
Lonny Wong
bfa67ecf0c pmd: revert and drain extensions before next ssl read 2023-11-24 05:52:12 +00:00
Yurii Nakonechnyi
0c1a090273 Subject: sul: Update README.lws_sul.md
Described `lws_container_of(...)` usage, added note about `lws_sorted_usec_list_t` zeroing.
2023-11-24 05:49:02 +00:00
Luka Kudra
f8eac4e83b mbedtls: dont rely on potentially missing version api
https://github.com/warmcat/libwebsockets/issues/3013
2023-11-21 17:10:54 +00:00
Lonny Wong
eba1e4aa7f pmd: fix buffer being reused while draining extensions 2023-11-21 17:10:48 +00:00
59 changed files with 741 additions and 469 deletions

View file

@ -368,6 +368,12 @@ if (LWS_WITHOUT_SERVER)
set(LWS_WITH_SERVER)
endif()
if (LWS_WITH_SERVER)
else()
set(LWS_WITH_CGI 0)
set(LWS_ROLE_CGI 0)
endif()
# using any abstract protocol enables LWS_WITH_ABSTRACT
#if (LWS_WITH_SMTP)

View file

@ -353,7 +353,7 @@ https://www.wolfssl.com/wolfSSL/Products-wolfssl.html
It contains a OpenSSL compatibility layer which makes it possible to pretty
much link to it instead of OpenSSL, giving a much smaller footprint.
**NOTE**: wolfssl needs to be compiled using the `--enable-opensslextra` flag for
**NOTE**: wolfssl needs to be compiled using the `--enable-libwebsockets` flag for
this to work.
@section wolf1 Compiling libwebsockets with wolfSSL

View file

@ -30,33 +30,44 @@ scheduler from your own code; it uses it to spread out connection
attempts so they are staggered in time. You must create an
`lws_sorted_usec_list_t` object somewhere, eg, in you own existing object.
```
```c
static lws_sorted_usec_list_t sul_stagger;
```
Create your own callback for the event... the argument points to the sul object
used when the callback was scheduled. You can use pointer arithmetic to translate
that to your own struct when the `lws_sorted_usec_list_t` was a member of the
same struct.
that to your own struct (when the `lws_sorted_usec_list_t` was a member of the
some struct) by using `lws_container_of(sul, container_struct_type, field_name)`.
```c
typedef struct my_connection_data {
...
lws_sorted_usec_list_t sul_stagger;
...
} my_connection_data_t;
```
static void
stagger_cb(lws_sorted_usec_list_t *sul)
{
...
my_connection_data_t* my_data = lws_container_of(sul, my_connection_data_t, sul_stagger);
...
}
```
**Important note**: make sure, that `lws_sorted_usec_list_t` data initiallized by
zeros (`memset(&sul_stagger, 0, sizeof(lws_sorted_usec_list_t)`). This struct
contains pointers, so them must initially pointing to `NULL`!
When you want to schedule the callback, use `lws_sul_schedule()`... this will call
it 10ms in the future
```
```c
lws_sul_schedule(context, 0, &sul_stagger, stagger_cb, 10 * LWS_US_PER_MS);
```
In the case you destroy your object and need to cancel the scheduled callback, use
```
```c
lws_sul_schedule(context, 0, &sul_stagger, NULL, LWS_SET_TIMER_USEC_CANCEL);
```

View file

@ -43,8 +43,10 @@ valid session object.
### Difference from Session Tickets
TLS also supports sessions as bearer tokens, but these are generally considered
as degrading security. Lws doesn't support Session Tickets, just reuse by
Session IDs.
as degrading security. Lws doesn't do anything special for Session Tickets, but
it's possible your TLS library will support them by default, as is reportedly the
case with mbedtls 2.28.1. Either way, it's expected Session IDs should work with
lws if enabled and your tls library supports them.
## Support in lws

View file

@ -24,13 +24,13 @@ CMAKE_OPTIONS += -DLWS_WITH_SSL=ON
CMAKE_OPTIONS += -DLWS_WITHOUT_TESTAPPS=$(if $(CONFIG_PACKAGE_libwebsockets-examples),"OFF","ON")
# for wolfssl, define these in addition to LWS_OPENSSL_SUPPORT and
# edit package/libs/wolfssl/Makefile to include --enable-opensslextra
# edit package/libs/wolfssl/Makefile to include --enable-libwebsockets
# CMAKE_OPTIONS += -DLWS_WITH_WOLFSSL=ON
# CMAKE_OPTIONS += -DLWS_WOLFSSL_LIBRARIES=$(STAGING_DIR)/usr/lib/libwolfssl.so
# CMAKE_OPTIONS += -DLWS_WOLFSSL_INCLUDE_DIRS=$(STAGING_DIR)/usr/include
# for cyassl, define these in addition to LWS_OPENSSL_SUPPORT and
# edit package/libs/wolfssl/Makefile to include --enable-opensslextra
# edit package/libs/wolfssl/Makefile to include --enable-libwebsockets
# CMAKE_OPTIONS += -DLWS_WITH_CYASSL=ON
# CMAKE_OPTIONS += -DLWS_CYASSL_LIBRARIES=$(STAGING_DIR)/usr/lib/libcyassl.so
# CMAKE_OPTIONS += -DLWS_CYASSL_INCLUDE_DIRS=$(STAGING_DIR)/usr/include

View file

@ -88,8 +88,8 @@ typedef unsigned long long lws_intptr_t;
#define O_RDONLY _O_RDONLY
#endif
typedef int uid_t;
typedef int gid_t;
typedef unsigned int uid_t;
typedef unsigned int gid_t;
typedef unsigned short sa_family_t;
#if !defined(LWS_HAVE_SUSECONDS_T)
typedef unsigned int useconds_t;
@ -132,7 +132,7 @@ typedef int suseconds_t;
#define LWS_O_CREAT _O_CREAT
#define LWS_O_TRUNC _O_TRUNC
#ifndef __func__
#if (__STDC_VERSION__ < 199901L) && !defined(__func__)
#define __func__ __FUNCTION__
#endif

View file

@ -89,7 +89,7 @@ struct lws_genaes_ctx {
char underway;
};
/** lws_genaes_create() - Create RSA public decrypt context
/** lws_genaes_create() - Create genaes AES context
*
* \param ctx: your struct lws_genaes_ctx
* \param op: LWS_GAESO_ENC or LWS_GAESO_DEC
@ -98,7 +98,7 @@ struct lws_genaes_ctx {
* \param padding: 0 = no padding, 1 = padding
* \param engine: if openssl engine used, pass the pointer here
*
* Creates an RSA context with a public key associated with it, formed from
* Creates an AES context with a key associated with it, formed from
* the key elements in \p el.
*
* Returns 0 for OK or nonzero for error.

View file

@ -184,7 +184,7 @@ lws_ext_parse_options(const struct lws_extension *ext, struct lws *wsi,
*
* Built-in callback implementing RFC7692 permessage-deflate
*/
LWS_EXTERN int
LWS_VISIBLE LWS_EXTERN int
lws_extension_callback_pm_deflate(struct lws_context *context,
const struct lws_extension *ext,
struct lws *wsi,

View file

@ -217,7 +217,7 @@ lws_client_connect_3_connect(struct lws *wsi, const char *ads,
*/
lwsi_set_state(wsi, LRS_UNCONNECTED);
lws_sul_schedule(wsi->a.context, 0, &wsi->sul_connect_timeout,
lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->sul_connect_timeout,
lws_client_dns_retry_timeout,
LWS_USEC_PER_SEC);
return wsi;
@ -601,7 +601,7 @@ ads_known:
* uses wsi->sul_connect_timeout just for this purpose
*/
lws_sul_schedule(wsi->a.context, 0, &wsi->sul_connect_timeout,
lws_sul_schedule(wsi->a.context, wsi->tsi, &wsi->sul_connect_timeout,
lws_client_conn_wait_timeout,
wsi->a.context->timeout_secs *
LWS_USEC_PER_SEC);
@ -728,6 +728,7 @@ try_next_dns_result:
lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
failed1:
lws_sul_cancel(&wsi->sul_connect_timeout);
lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "client_connect3");
return NULL;

View file

@ -279,7 +279,7 @@ send_hs:
pfd.revents = LWS_POLLOUT;
lwsl_wsi_info(wsi, "going to service fd");
n = lws_service_fd(wsi->a.context, &pfd);
n = lws_service_fd_tsi(wsi->a.context, &pfd, wsi->tsi);
if (n < 0) {
cce = "first service failed";
goto failed;
@ -318,7 +318,7 @@ provoke_service:
pfd.events = LWS_POLLIN;
pfd.revents = LWS_POLLIN;
n = lws_service_fd(wsi->a.context, &pfd);
n = lws_service_fd_tsi(wsi->a.context, &pfd, wsi->tsi);
if (n < 0) {
cce = "first service failed";
goto failed;

View file

@ -881,9 +881,19 @@ __lws_close_free_wsi_final(struct lws *wsi)
if (!wsi->shadow &&
lws_socket_is_valid(wsi->desc.sockfd) && !lws_ssl_close(wsi)) {
lwsl_wsi_debug(wsi, "fd %d", wsi->desc.sockfd);
n = compatible_close(wsi->desc.sockfd);
if (n)
lwsl_wsi_debug(wsi, "closing: close ret %d", LWS_ERRNO);
/*
* if this is the pt pipe, skip the actual close,
* go through the motions though so we will reach 0 open wsi
* on the pt, and trigger the pt destroy to close the pipe fds
*/
if (!lws_plat_pipe_is_fd_assocated(wsi->a.context, wsi->tsi,
wsi->desc.sockfd)) {
n = compatible_close(wsi->desc.sockfd);
if (n)
lwsl_wsi_debug(wsi, "closing: close ret %d",
LWS_ERRNO);
}
__remove_wsi_socket_from_fds(wsi);
if (lws_socket_is_valid(wsi->desc.sockfd))

View file

@ -1326,6 +1326,8 @@ int
lws_plat_pipe_signal(struct lws_context *ctx, int tsi);
void
lws_plat_pipe_close(struct lws *wsi);
int
lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd);
void
lws_addrinfo_clean(struct lws *wsi);

View file

@ -1305,7 +1305,7 @@ lws_mux_mark_immortal(struct lws *wsi)
&& !wsi->client_mux_substream
#endif
) {
lwsl_wsi_err(wsi, "not mux substream");
// lwsl_wsi_err(wsi, "not mux substream");
return;
}

View file

@ -386,9 +386,6 @@ lws_create_context(const struct lws_context_creation_info *info)
#if defined(LWS_WITH_CACHE_NSCOOKIEJAR) && defined(LWS_WITH_CLIENT)
struct lws_cache_creation_info ci;
#endif
#if defined(LWS_WITH_MBEDTLS)
char mbedtls_version[32];
#endif
#if defined(__ANDROID__)
struct rlimit rt;
@ -545,6 +542,11 @@ lws_create_context(const struct lws_context_creation_info *info)
fatal_exit_defer = !!info->foreign_loops;
us_wait_resolution = 0;
}
#else
if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBUV)) {
lwsl_cx_err(context, "Application wants libuv, but lws not built with it");
goto bail;
}
#endif
#if defined(LWS_WITH_LIBEVENT)
@ -553,6 +555,11 @@ lws_create_context(const struct lws_context_creation_info *info)
plev = &evlib_event;
us_wait_resolution = 0;
}
#else
if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEVENT)) {
lwsl_cx_err(context, "Application wants libevent, but lws not built with it");
goto bail;
}
#endif
#if defined(LWS_WITH_GLIB)
@ -561,6 +568,11 @@ lws_create_context(const struct lws_context_creation_info *info)
plev = &evlib_glib;
us_wait_resolution = 0;
}
#else
if (lws_check_opt(info->options, LWS_SERVER_OPTION_GLIB)) {
lwsl_cx_err(context, "Application wants glib, but lws not built with it");
goto bail;
}
#endif
#if defined(LWS_WITH_LIBEV)
@ -569,6 +581,11 @@ lws_create_context(const struct lws_context_creation_info *info)
plev = &evlib_ev;
us_wait_resolution = 0;
}
#else
if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBEV)) {
lwsl_cx_err(context, "Application wants libev, but lws not built with it");
goto bail;
}
#endif
#if defined(LWS_WITH_SDEVENT)
@ -577,6 +594,11 @@ lws_create_context(const struct lws_context_creation_info *info)
plev = &evlib_sd;
us_wait_resolution = 0;
}
#else
if (lws_check_opt(info->options, LWS_SERVER_OPTION_SDEVENT)) {
lwsl_cx_err(context, "Application wants sdevent, but lws not built with it");
goto bail;
}
#endif
#if defined(LWS_WITH_ULOOP)
@ -585,6 +607,11 @@ lws_create_context(const struct lws_context_creation_info *info)
plev = &evlib_uloop;
us_wait_resolution = 0;
}
#else
if (lws_check_opt(info->options, LWS_SERVER_OPTION_ULOOP)) {
lwsl_cx_err(context, "Application wants uloop, but lws not built with it");
goto bail;
}
#endif
#endif /* with event libs */
@ -788,11 +815,16 @@ lws_create_context(const struct lws_context_creation_info *info)
#endif /* network */
#if defined(LWS_WITH_MBEDTLS)
mbedtls_version_get_string(mbedtls_version);
#endif
{
char mbedtls_version[32];
#if defined(LWS_WITH_MBEDTLS)
lwsl_cx_notice(context, "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s);
#if defined(MBEDTLS_VERSION_C)
mbedtls_version_get_string(mbedtls_version);
#else
lws_snprintf(mbedtls_version, sizeof(mbedtls_version), "%s", MBEDTLS_VERSION_STRING);
#endif
lwsl_cx_notice(context, "LWS: %s, MbedTLS-%s %s%s", library_version, mbedtls_version, opts_str, s);
}
#else
lwsl_cx_notice(context, "LWS: %s, %s%s", library_version, opts_str, s);
#endif

View file

@ -29,11 +29,11 @@ typedef struct lws_map_hashtable {
lws_dll2_owner_t ho;
} lws_map_hashtable_t;
typedef struct lws_map {
struct lws_map {
lws_map_info_t info;
/* array of info.modulo x lws_map_hashtable_t overallocated */
} lws_map_t;
};
typedef struct lws_map_item {
lws_dll2_t list; /* owned by hashtable */
@ -88,7 +88,10 @@ lws_map_hash_from_key_default(const lws_map_key_t key, size_t kl)
const uint8_t *u = (const uint8_t *)key;
while (kl--)
h = ((((h << 7) | (h >> 25)) + 0xa1b2c3d4) ^ (*u++)) ^ h;
h = ((
(((h & 0x1fffffff /* coverity */ ) << 7) |
(h >> 25)) +
0xa1b2c3d4) ^ (*u++)) ^ h;
return h;
}

View file

@ -94,6 +94,7 @@ lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
struct lws_context_per_thread *pt;
struct lws_pollfd eventfd;
struct lws *wsi;
int tsi = 0;
if (revents & EV_ERROR)
return;
@ -112,10 +113,12 @@ lws_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents)
}
wsi = wsi_from_fd(context, watcher->fd);
pt = &context->pt[(int)wsi->tsi];
if (wsi)
tsi = (int)wsi->tsi;
pt = &context->pt[tsi];
ptpr = pt_to_priv_ev(pt);
lws_service_fd_tsi(context, &eventfd, (int)wsi->tsi);
lws_service_fd_tsi(context, &eventfd, tsi);
ev_idle_start(ptpr->io_loop, &ptpr->idle);
}
@ -136,6 +139,7 @@ lws_ev_sigint_cb(struct ev_loop *loop, struct ev_signal *watcher, int revents)
static int
elops_listen_init_ev(struct lws_dll2 *d, void *user)
{
#if defined(LWS_WITH_SERVER)
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
struct lws_context *context = (struct lws_context *)user;
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
@ -150,6 +154,7 @@ elops_listen_init_ev(struct lws_dll2 *d, void *user)
ev_io_init(&vh_to_priv_ev(vh)->w_accept.watcher,
lws_accept_cb, wsi->desc.sockfd, EV_READ);
ev_io_start(ptpr->io_loop, &vh_to_priv_ev(vh)->w_accept.watcher);
#endif
return 0;
}
@ -240,6 +245,7 @@ elops_init_pt_ev(struct lws_context *context, void *_loop, int tsi)
static int
elops_listen_destroy_ev(struct lws_dll2 *d, void *user)
{
#if defined(LWS_WITH_SERVER)
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
struct lws_context *context = (struct lws_context *)user;
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
@ -247,7 +253,7 @@ elops_listen_destroy_ev(struct lws_dll2 *d, void *user)
struct lws_vhost *vh = wsi->a.vhost;
ev_io_stop(ptpr->io_loop, &vh_to_priv_ev(vh)->w_accept.watcher);
#endif
return 0;
}
@ -413,6 +419,14 @@ elops_destroy_wsi_ev(struct lws *wsi)
ev_io_stop(ptpr->io_loop, &w->w_write.watcher);
}
static int
elops_wsi_logical_close_ev(struct lws *wsi)
{
elops_destroy_wsi_ev(wsi);
return 0;
}
static const struct lws_event_loop_ops event_loop_ops_ev = {
/* name */ "libev",
/* init_context */ elops_init_context_ev,
@ -420,7 +434,7 @@ static const struct lws_event_loop_ops event_loop_ops_ev = {
/* destroy_context2 */ elops_destroy_context2_ev,
/* init_vhost_listen_wsi */ elops_init_vhost_listen_wsi_ev,
/* init_pt */ elops_init_pt_ev,
/* wsi_logical_close */ NULL,
/* wsi_logical_close */ elops_wsi_logical_close_ev,
/* check_client_connect_ok */ NULL,
/* close_handle_manually */ NULL,
/* accept */ elops_accept_ev,

View file

@ -176,6 +176,7 @@ lws_event_sigint_cb(evutil_socket_t sock_fd, short revents, void *ctx)
static int
elops_listen_init_event(struct lws_dll2 *d, void *user)
{
#if defined(LWS_WITH_SERVER)
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
struct lws_context *context = (struct lws_context *)user;
struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
@ -188,6 +189,7 @@ elops_listen_init_event(struct lws_dll2 *d, void *user)
(EV_READ | EV_PERSIST), lws_event_cb, w_read);
event_add(w_read->watcher, NULL);
w_read->set = 1;
#endif
return 0;
}
@ -334,6 +336,7 @@ elops_run_pt_event(struct lws_context *context, int tsi)
static int
elops_listen_destroy_event(struct lws_dll2 *d, void *user)
{
#if defined(LWS_WITH_SERVER)
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
struct lws_wsi_eventlibs_libevent *w = wsi_to_priv_event(wsi);
@ -341,6 +344,7 @@ elops_listen_destroy_event(struct lws_dll2 *d, void *user)
w->w_read.watcher = NULL;
event_free(w->w_write.watcher);
w->w_write.watcher = NULL;
#endif
return 0;
}

View file

@ -698,10 +698,12 @@ elops_destroy_pt_uv(struct lws_context *context, int tsi)
static int
elops_listen_init_uv(struct lws_dll2 *d, void *user)
{
#if defined(LWS_WITH_SERVER)
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
if (elops_init_vhost_listen_wsi_uv(wsi) == -1)
return -1;
#endif
return 0;
}

View file

@ -234,10 +234,12 @@ init_vhost_listen_wsi_sd(struct lws *wsi)
static int
elops_listen_init_sdevent(struct lws_dll2 *d, void *user)
{
#if defined(LWS_WITH_SERVER)
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
if (init_vhost_listen_wsi_sd(wsi) == -1)
return -1;
#endif
return 0;
}
@ -368,9 +370,11 @@ run_pt_sd(struct lws_context *context, int tsi)
static int
elops_listen_destroy_sdevent(struct lws_dll2 *d, void *user)
{
#if defined(LWS_WITH_SERVER)
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
wsi_logical_close_sd(wsi);
#endif
return 0;
}

View file

@ -135,6 +135,7 @@ lws_uloop_cb(struct uloop_fd *ufd, unsigned int revents)
static int
elops_listen_init_uloop(struct lws_dll2 *d, void *user)
{
#if defined(LWS_WITH_SERVER)
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi);
@ -143,6 +144,7 @@ elops_listen_init_uloop(struct lws_dll2 *d, void *user)
wu->fd.cb = lws_uloop_cb;
uloop_fd_add(&wu->fd, ULOOP_READ);
wu->actual_events = ULOOP_READ;
#endif
return 0;
}
@ -217,10 +219,12 @@ elops_run_pt_uloop(struct lws_context *context, int tsi)
static int
elops_listen_destroy_uloop(struct lws_dll2 *d, void *user)
{
#if defined(LWS_WITH_SERVER)
struct lws *wsi = lws_container_of(d, struct lws, listen_list);
struct lws_wsi_eventlibs_uloop *wu = wsi_to_priv_uloop(wsi);
uloop_fd_delete(&wu->fd);
#endif
return 0;
}

View file

@ -163,7 +163,11 @@ nscookiejar_iterate(lws_cache_nscookiejar_t *cache, int fd,
lwsl_debug("%s: n %d, m %d\n", __func__, n, m);
read:
n1 = (int)read(fd, temp + n, sizeof(temp) - (size_t)n);
if ((size_t)n >= sizeof(temp) - 1)
/* there's no space left in temp */
n1 = 0;
else
n1 = (int)read(fd, temp + n, sizeof(temp) - (size_t)n);
lwsl_debug("%s: n1 %d\n", __func__, n1);
@ -171,12 +175,18 @@ read:
eof = 1;
if (m == n)
continue;
} else
} else {
n += n1;
if ((size_t)n > sizeof(temp)) { /* coverity */
ret = -1;
goto bail;
}
}
while (m < n) {
m++;
m++; /* m can == n nw then */
if (temp[m - 1] != '\n')
continue;
@ -197,6 +207,13 @@ read:
* cb can classify it even if it can't get all the
* value part in one go
*/
/* coverity: we will blow up if m > n */
if (m > n) {
ret = -1;
goto bail;
}
memmove(temp, temp + m, (size_t)(n - m));
n -= m;
m = 0;

View file

@ -6,12 +6,12 @@
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicefsme, and/or
* sell copies of the Software, and to permit persofsm to whom the Software is
* furnished to do so, subject to the following conditiofsm:
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portiofsm of the Software.
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

View file

@ -985,7 +985,7 @@ format_scan(const char *fmt)
}
if (numeric) {
if (*fmt >= '0' && *fmt <= '9')
while (*fmt >= '0' && *fmt <= '9')
fmt++;
numeric = 0;
if (*fmt != '(')
@ -1119,6 +1119,7 @@ pop:
return count[0];
case '-':
case '0':
case '1':
case '2':

View file

@ -580,7 +580,8 @@ lejp_parse(struct lejp_ctx *ctx, const unsigned char *json, int len)
}
ctx->buf[ctx->npos] = '\0';
if (ctx->f & LEJP_SEEN_POINT) {
if (ctx->f & (LEJP_SEEN_POINT | LEJP_SEEN_EXP)) {
/* 0.001 or 1E-3 are both floats, take 1E3 as float too */
if (ctx->pst[ctx->pst_sp].callback(ctx,
LEJPCB_VAL_NUM_FLOAT))
goto reject_callback;

View file

@ -124,3 +124,11 @@ lws_plat_pipe_close(struct lws *wsi)
fd[0] = fd[1] = -1;
}
int
lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd)
{
struct lws_context_per_thread *pt = &cx->pt[tsi];
return fd == pt->dummy_pipe_fds[0] || fd == pt->dummy_pipe_fds[1];
}

View file

@ -49,6 +49,12 @@ lws_plat_pipe_close(struct lws *wsi)
{
}
int
lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd)
{
return 0;
}
int
lws_send_pipe_choked(struct lws *wsi)
{

View file

@ -83,7 +83,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
const char *vpath, lws_fop_flags_t *flags)
{
struct stat stat_buf;
int ret = lws_open(filename, (*flags) & LWS_FOP_FLAGS_MASK, 0664);
int ret = lws_open(filename, (int)((*flags) & LWS_FOP_FLAGS_MASK), 0664);
lws_fop_fd_t fop_fd;
if (ret < 0)

View file

@ -240,4 +240,9 @@ lws_plat_context_late_destroy(struct lws_context *context)
lwsl_err("ZERO RANDOM FD\n");
if (context->fd_random != LWS_INVALID_FILE)
close(context->fd_random);
#if defined(LWS_WITH_MBEDTLS)
mbedtls_entropy_free(&context->mec);
mbedtls_ctr_drbg_free(&context->mcdc);
#endif
}

View file

@ -84,10 +84,20 @@ lws_plat_pipe_close(struct lws *wsi)
{
struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
if (pt->dummy_pipe_fds[0] && pt->dummy_pipe_fds[0] != -1)
if (pt->dummy_pipe_fds[0] && pt->dummy_pipe_fds[0] != -1) {
close(pt->dummy_pipe_fds[0]);
if (pt->dummy_pipe_fds[1] && pt->dummy_pipe_fds[1] != -1)
pt->dummy_pipe_fds[0] = -1;
}
if (pt->dummy_pipe_fds[1] && pt->dummy_pipe_fds[1] != -1) {
close(pt->dummy_pipe_fds[1]);
pt->dummy_pipe_fds[0] = pt->dummy_pipe_fds[1] = -1;
pt->dummy_pipe_fds[1] = -1;
}
}
int
lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd)
{
struct lws_context_per_thread *pt = &cx->pt[tsi];
return fd == pt->dummy_pipe_fds[0] || fd == pt->dummy_pipe_fds[1];
}

View file

@ -191,21 +191,23 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, int fd, int unix_skt)
}
static const int ip_opt_lws_flags[] = {
LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT,
LCCSCF_IP_HIGH_RELIABILITY
#if !defined(__OpenBSD__)
LCCSCF_IP_LOW_LATENCY, LCCSCF_IP_HIGH_THROUGHPUT
#if !defined(__OpenBSD__) && !defined(__sun) && !defined(__QNX__)
, LCCSCF_IP_HIGH_RELIABILITY
, LCCSCF_IP_LOW_COST
#endif
}, ip_opt_val[] = {
IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_RELIABILITY
IPTOS_LOWDELAY, IPTOS_THROUGHPUT
#if !defined(__OpenBSD__) && !defined(__sun) && !defined(__QNX__)
, IPTOS_RELIABILITY
, IPTOS_MINCOST
#endif
};
#if !defined(LWS_WITH_NO_LOGS)
static const char *ip_opt_names[] = {
"LOWDELAY", "THROUGHPUT", "RELIABILITY"
#if !defined(__OpenBSD__) && !defined(__sun)
"LOWDELAY", "THROUGHPUT"
#if !defined(__OpenBSD__) && !defined(__sun) && !defined(__QNX__)
, "RELIABILITY"
, "MINCOST"
#endif
};
@ -255,7 +257,10 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
}
#endif
for (n = 0; n < 4; n++) {
#if !defined(__NuttX__)
/* array size differs by platform */
for (n = 0; n < (int)LWS_ARRAY_SIZE(ip_opt_lws_flags); n++) {
if (!(lws_flags & ip_opt_lws_flags[n]))
continue;
@ -272,6 +277,7 @@ lws_plat_set_socket_options_ip(lws_sockfd_type fd, uint8_t pri, int lws_flags)
lwsl_notice("%s: set ip flag %s\n", __func__,
ip_opt_names[n]);
}
#endif
return ret;
}
@ -435,7 +441,7 @@ lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, size_t canned_len,
p[3] = (uint8_t)(n);
while (p16 < (uint16_t *)(p + 20))
ucs += ntohs(*p16++);
ucs = ucs + (uint32_t)(ntohs((uint16_t)(*p16++)));
ucs += ucs >> 16;
ucs ^= 0xffff;
@ -447,7 +453,7 @@ lws_plat_rawudp_broadcast(uint8_t *p, const uint8_t *canned, size_t canned_len,
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(0x800);
sll.sll_protocol = (uint32_t)(htons((uint16_t)0x800));
sll.sll_halen = 6;
sll.sll_ifindex = (int)if_nametoindex(iface);
memset(sll.sll_addr, 0xff, 6);

View file

@ -549,8 +549,10 @@ lws_spawn_piped(const struct lws_spawn_piped_info *i)
int naml = lws_ptr_diff(p, i->env_array[m]);
char enam[32];
lws_strnncpy(enam, i->env_array[m], naml, sizeof(enam));
setenv(enam, p, 1);
if (p) {
lws_strnncpy(enam, i->env_array[m], naml, sizeof(enam));
setenv(enam, p + 1, 1);
}
m++;
}
#endif

View file

@ -49,7 +49,7 @@ _lws_plat_file_open(const struct lws_plat_file_ops *fops, const char *filename,
ret = CreateFileW(buf, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (ret == NULL)
if (ret == INVALID_HANDLE_VALUE)
goto bail;
fop_fd = malloc(sizeof(*fop_fd));

View file

@ -125,3 +125,11 @@ lws_plat_pipe_close(struct lws *wsi)
pt->dummy_pipe_fds[0] = pt->dummy_pipe_fds[1] = LWS_SOCK_INVALID;
}
int
lws_plat_pipe_is_fd_assocated(struct lws_context *cx, int tsi, lws_sockfd_type fd)
{
struct lws_context_per_thread *pt = &cx->pt[tsi];
return fd == pt->dummy_pipe_fds[0] || fd == pt->dummy_pipe_fds[1];
}

View file

@ -63,6 +63,7 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
struct lws_context_per_thread *pt;
struct lws_pollfd *pfd;
lws_usec_t timeout_us;
int64_t timeout_ms64 = (int64_t)timeout_ms;
struct lws *wsi;
unsigned int i;
int n;
@ -85,12 +86,12 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
pt->service_tid_detected = 1;
}
if (timeout_ms < 0)
timeout_ms = 0;
if (timeout_ms64 < 0)
timeout_ms64 = 0;
else
/* force a default timeout of 23 days */
timeout_ms = 2000000000;
timeout_us = ((lws_usec_t)timeout_ms) * LWS_US_PER_MS;
timeout_ms64 = 2000000000;
timeout_us = ((lws_usec_t)timeout_ms64) * LWS_US_PER_MS;
if (context->event_loop_ops->run_pt)
context->event_loop_ops->run_pt(context, tsi);
@ -176,6 +177,11 @@ _lws_plat_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
// lwsl_notice("%s: idx %d, revents 0x%x\n", __func__, n, pt->fds[n].revents);
lws_service_fd_tsi(context, &pt->fds[n], tsi);
}
if (pt->destroy_self) {
lws_context_destroy(pt->context);
return -1;
}
return 0;
}

View file

@ -81,10 +81,7 @@ lws_plat_set_nonblocking(lws_sockfd_type fd)
int result = !!ioctlsocket(fd, FIONBIO, &optl);
#if (_LWS_ENABLED_LOGS & LLL_ERR)
if (result)
{
int error = LWS_ERRNO;
lwsl_err("ioctlsocket FIONBIO 1 failed with error %d\n", error);
}
lwsl_err("ioctlsocket FIONBIO 1 failed with error %d\n", LWS_ERRNO);
#endif
return result;
}
@ -108,8 +105,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
(const char *)&optval, optlen) < 0) {
#if (_LWS_ENABLED_LOGS & LLL_ERR)
int error = LWS_ERRNO;
lwsl_err("setsockopt SO_KEEPALIVE 1 failed with error %d\n", error);
lwsl_err("setsockopt SO_KEEPALIVE 1 failed with error %d\n", LWS_ERRNO);
#endif
return 1;
}
@ -121,8 +117,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
if (WSAIoctl(fd, SIO_KEEPALIVE_VALS, &alive, sizeof(alive),
NULL, 0, &dwBytesRet, NULL, NULL)) {
#if (_LWS_ENABLED_LOGS & LLL_ERR)
int error = LWS_ERRNO;
lwsl_err("WSAIoctl SIO_KEEPALIVE_VALS 1 %lu %lu failed with error %d\n", alive.keepalivetime, alive.keepaliveinterval, error);
lwsl_err("WSAIoctl SIO_KEEPALIVE_VALS 1 %lu %lu failed with error %d\n", alive.keepalivetime, alive.keepaliveinterval, LWS_ERRNO);
#endif
return 1;
}
@ -134,8 +129,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
tcp_proto = getprotobyname("TCP");
if (!tcp_proto) {
#if (_LWS_ENABLED_LOGS & LLL_WARN)
int error = LWS_ERRNO;
lwsl_warn("getprotobyname(\"TCP\") failed with error, falling back to 6 %d\n", error);
lwsl_warn("getprotobyname(\"TCP\") failed with error, falling back to 6 %d\n", LWS_ERRNO);
#endif
protonbr = 6; /* IPPROTO_TCP */
} else
@ -146,8 +140,7 @@ lws_plat_set_socket_options(struct lws_vhost *vhost, lws_sockfd_type fd,
if (setsockopt(fd, protonbr, TCP_NODELAY, (const char *)&optval, optlen) ) {
#if (_LWS_ENABLED_LOGS & LLL_WARN)
int error = LWS_ERRNO;
lwsl_warn("setsockopt TCP_NODELAY 1 failed with error %d\n", error);
lwsl_warn("setsockopt TCP_NODELAY 1 failed with error %d\n", LWS_ERRNO);
#endif
}

View file

@ -2322,12 +2322,14 @@ lws_h2_parser(struct lws *wsi, unsigned char *in, lws_filepos_t _inlen,
(unsigned int)h2n->count,
(unsigned int)h2n->length);
in += (unsigned int)n - 1;
h2n->inside += (unsigned int)n;
h2n->count += (unsigned int)n - 1;
if (n) {
in += (unsigned int)n - 1;
h2n->inside += (unsigned int)n;
h2n->count += (unsigned int)n - 1;
h2n->swsi->txc.peer_tx_cr_est -= n;
wsi->txc.peer_tx_cr_est -= n;
h2n->swsi->txc.peer_tx_cr_est -= n;
wsi->txc.peer_tx_cr_est -= n;
}
do_windows:

View file

@ -227,11 +227,13 @@ read:
// lwsi_state(wsi) != LRS_H1C_ISSUE_HANDSHAKE2 &&
lwsi_state(wsi) != LRS_H2_WAITING_TO_SEND_HEADERS))) {
int scr_ret;
ebuf.token = pt->serv_buf;
ebuf.len = lws_ssl_capable_read(wsi,
scr_ret = lws_ssl_capable_read(wsi,
ebuf.token,
wsi->a.context->pt_serv_buf_size);
switch (ebuf.len) {
switch (scr_ret) {
case 0:
lwsl_info("%s: zero length read\n", __func__);
return LWS_HPI_RET_PLEASE_CLOSE_ME;
@ -243,6 +245,19 @@ read:
return LWS_HPI_RET_PLEASE_CLOSE_ME;
}
/*
* coverity is confused: it knows lws_ssl_capable_read may
* return < 0 and assigning that to ebuf.len is bad, but it
* doesn't understand this check below on scr_ret < 0
* removes that possibility
*/
ebuf.len = scr_ret;
if (ebuf.len < 0) /* ie, not usable data */ {
lwsl_info("%s: other error\n", __func__);
return LWS_HPI_RET_PLEASE_CLOSE_ME;
}
// lwsl_notice("%s: Actual RX %d\n", __func__, ebuf.len);
// if (ebuf.len > 0)
// lwsl_hexdump_notice(ebuf.token, ebuf.len);
@ -313,7 +328,8 @@ drain:
lws_dll2_remove(&wsi->dll_buflist);
}
} else
if (n && n < ebuf.len && ebuf.len > 0) {
/* cov: both n and ebuf.len are int */
if (n > 0 && n < ebuf.len && ebuf.len > 0) {
// lwsl_notice("%s: h2 append seg %d\n", __func__, ebuf.len - n);
m = lws_buflist_append_segment(&wsi->buflist,
ebuf.token + n,

View file

@ -1255,6 +1255,8 @@ lws_generate_client_handshake(struct lws *wsi, char *pkt)
// if (!wsi->client_pipeline)
// conn1 = "close, ";
p = lws_generate_client_ws_handshake(wsi, p, conn1);
if (!p)
return NULL;
} else
#endif
{

View file

@ -160,11 +160,13 @@ lws_cookie_rm_sws(const char **buf_p, size_t *len_p)
buf = *buf_p;
len = *len_p;
while (buf[0] == ' ' && len > 0) {
buf++;
len--;
}
while (buf[len - 1] == ' ' && len > 0)
while (len && buf[len - 1] == ' ')
len--;
*buf_p = buf;

View file

@ -570,7 +570,7 @@ lws_spa_create_via_info(struct lws *wsi, const lws_spa_create_info_t *i)
if (!spa->storage)
goto bail2;
spa->end = spa->storage + i->max_storage - 1;
spa->end = spa->storage + spa->i.max_storage - 1;
if (i->count_params) {
if (i->ac)
@ -583,7 +583,7 @@ lws_spa_create_via_info(struct lws *wsi, const lws_spa_create_info_t *i)
goto bail3;
}
spa->s = lws_urldecode_s_create(spa, wsi, spa->storage, i->max_storage,
spa->s = lws_urldecode_s_create(spa, wsi, spa->storage, spa->i.max_storage,
lws_urldecode_spa_cb);
if (!spa->s)
goto bail4;

View file

@ -345,9 +345,11 @@ done_list:
if (setsockopt(wsi->desc.sockfd, IPPROTO_TCP,
TCP_FASTOPEN,
(const char*)&optval, sizeof(optval)) < 0) {
#if (_LWS_ENABLED_LOGS & LLL_WARN)
int error = LWS_ERRNO;
lwsl_warn("%s: TCP_NODELAY failed with error %d\n",
__func__, error);
#endif
}
}
#else

View file

@ -526,7 +526,6 @@ rops_pt_init_destroy_netlink(struct lws_context *context,
memset(&sanl, 0, sizeof(sanl));
sanl.nl_family = AF_NETLINK;
sanl.nl_pid = (uint32_t)getpid();
sanl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR
#if defined(LWS_WITH_IPV6)
| RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR

View file

@ -60,12 +60,14 @@ lws_raw_skt_connect(struct lws *wsi)
}
#endif
n = user_callback_handle_rxflow(wsi->a.protocol->callback,
wsi, wsi->role_ops->adoption_cb[lwsi_role_server(wsi)],
wsi->user_space, NULL, 0);
if (n) {
lws_inform_client_conn_fail(wsi, (void *)"user", 4);
return 1;
if (!wsi->hdr_parsing_completed) {
n = user_callback_handle_rxflow(wsi->a.protocol->callback,
wsi, wsi->role_ops->adoption_cb[lwsi_role_server(wsi)],
wsi->user_space, NULL, 0);
if (n) {
lws_inform_client_conn_fail(wsi, (void *)"user", 4);
return 1;
}
}
lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
@ -172,7 +174,7 @@ rops_handle_POLLIN_raw_skt(struct lws_context_per_thread *pt, struct lws *wsi,
#endif
default:
ebuf.token = NULL;
ebuf.len = 0;
ebuf.len = (int) wsi->a.protocol->rx_buffer_size;
buffered = lws_buflist_aware_read(pt, wsi, &ebuf, 1, __func__);
switch (ebuf.len) {

View file

@ -943,7 +943,7 @@ rops_handle_POLLIN_ws(struct lws_context_per_thread *pt, struct lws *wsi,
unsigned int pending = 0;
struct lws_tokens ebuf;
char buffered = 0;
int n = 0, m, sanity = 10;
int n = 0, m, sanity = 100;
#if defined(LWS_WITH_HTTP2)
struct lws *wsi1;
#endif
@ -1223,8 +1223,18 @@ drain:
else
pending = pending > wsi->a.context->pt_serv_buf_size ?
wsi->a.context->pt_serv_buf_size : pending;
if (--sanity)
if (--sanity) {
#if !defined(LWS_WITHOUT_EXTENSIONS)
while (wsi->ws->rx_draining_ext) {
// RX Extension needs to be drained before next read
n = lws_ws_rx_sm(wsi, ALREADY_PROCESSED_IGNORE_CHAR, 0);
if (n < 0) {
return LWS_HPI_RET_PLEASE_CLOSE_ME;
}
}
#endif
goto read;
}
else
/*
* Something has gone wrong, we are spinning...

View file

@ -57,3 +57,9 @@ lws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type,
int
lws_x509_get_crt_ext(mbedtls_x509_crt *crt, mbedtls_x509_buf *skid,
lws_mbedtls_x509_authority *akid);
#if (MBEDTLS_VERSION_MAJOR == 3) && (MBEDTLS_VERSION_MINOR >= 5)
int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
mbedtls_x509_name *cur);
#endif

View file

@ -421,24 +421,38 @@ int ssl_pm_clear(SSL *ssl)
int ssl_pm_read(SSL *ssl, void *buffer, int len)
{
int ret;
struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
int ret;
struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
ret = mbedtls_ssl_read(&ssl_pm->ssl, buffer, (size_t)len);
if (ret < 0) {
// lwsl_notice("%s: mbedtls_ssl_read says -0x%x\n", __func__, -ret);
SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_read() return -0x%x", -ret);
if (ret == MBEDTLS_ERR_NET_CONN_RESET ||
ret = mbedtls_ssl_read(&ssl_pm->ssl, buffer, (size_t)len);
if (ret < 0) {
// lwsl_notice("%s: mbedtls_ssl_read says -0x%x\n", __func__, -ret);
SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_read() return -0x%x", -ret);
if (ret == MBEDTLS_ERR_NET_CONN_RESET ||
#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000
ret <= MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE) /* fatal errors */
ret <= MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE) /* fatal errors */
#else
ret <= MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) /* fatal errors */
ret <= MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) /* fatal errors */
#endif
ssl->err = SSL_ERROR_SYSCALL;
ret = -1;
}
return ret;
switch (ret) {
case MBEDTLS_ERR_NET_CONN_RESET:
ssl->err = SSL_ERROR_SYSCALL;
break;
case MBEDTLS_ERR_SSL_WANT_WRITE:
ssl->err = SSL_ERROR_WANT_WRITE;
break;
case MBEDTLS_ERR_SSL_WANT_READ:
ssl->err = SSL_ERROR_WANT_READ;
break;
default:
break;
}
ret = -1;
}
return ret;
}
/*

View file

@ -308,7 +308,7 @@ lws_tls_server_certs_load(struct lws_vhost *vhost, struct lws *wsi,
flen);
}
#else
ret = wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p, flen,
ret = wolfSSL_CTX_use_PrivateKey_buffer(vhost->tls.ssl_ctx, p, (long) flen,
WOLFSSL_FILETYPE_ASN1);
#endif
lws_free_set_NULL(p);
@ -439,7 +439,7 @@ check_key:
lwsl_notice(" Using ECDH certificate support\n");
/* Get X509 certificate from ssl context */
#if !defined(LWS_WITH_BORINGSSL)
#if !defined(LWS_WITH_BORINGSSL) && !defined(USE_WOLFSSL)
#if !defined(LWS_HAVE_SSL_EXTRA_CHAIN_CERTS)
x = sk_X509_value(vhost->tls.ssl_ctx->extra_certs, 0);
#else
@ -482,7 +482,7 @@ check_key:
EC_KEY_free(EC_key);
#if !defined(OPENSSL_NO_EC) && !defined(LWS_WITH_BORINGSSL)
#if !defined(OPENSSL_NO_EC) && !defined(LWS_WITH_BORINGSSL) && !defined(USE_WOLFSSL)
post_ecdh:
#endif
vhost->tls.skipped_certs = 0;

View file

@ -97,8 +97,9 @@ lws_context_init_ssl_library(struct lws_context *cx,
#endif
#endif
if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) {
lwsl_cx_info(cx, " SSL disabled: no "
"LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT");
if (!info->provided_client_ssl_ctx)
lwsl_cx_info(cx, " SSL disabled: no "
"LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT");
return 0;
}

View file

@ -47,11 +47,13 @@ lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as)
memset(&t, 0, sizeof(t));
if (strlen(p) == 13) {
t.tm_year = (dec(p[0]) * 10) + dec(p[1]) + 100;
t.tm_year = (dec(p[0]) * 10) + dec(p[1]);
if (t.tm_year < 50) /* RFC5280: 13 char dates will break after 2049 */
t.tm_year += 100; /* struct tm year is -1900, this gives 2000..2049 */
p += 2;
} else {
t.tm_year = (dec(p[0]) * 1000) + (dec(p[1]) * 100) +
(dec(p[2]) * 10) + dec(p[3]);
t.tm_year = ((dec(p[0]) * 1000) + (dec(p[1]) * 100) +
(dec(p[2]) * 10) + dec(p[3])) - 1900; /* struct tm year is -1900 */
p += 4;
}
t.tm_mon = (dec(p[0]) * 10) + dec(p[1]) - 1;

View file

@ -138,9 +138,6 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info,
if (info->client_ssl_ca_filepath)
ca_filepath = info->client_ssl_ca_filepath;
if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
return 0;
if (vhost->tls.ssl_client_ctx)
return 0;
@ -155,6 +152,9 @@ int lws_context_init_client_ssl(const struct lws_context_creation_info *info,
}
#endif
if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
return 0;
if (lws_tls_client_create_vhost_context(vhost, info, cipher_list,
ca_filepath,
info->client_ssl_ca_mem,

View file

@ -34,7 +34,7 @@ lws_tls_session_tag_discrete(const char *vhname, const char *host,
* different client certs.
*/
lws_snprintf(buf, len, "%s_%s_%u", vhname, host, port);
lws_snprintf(buf, len, "%s_%s_%u", vhname, host, (unsigned int)port);
}
int

View file

@ -4477,7 +4477,11 @@ static const uint8_t
w26[] = { 0xF9, 0x3E, 0x00 },
w27[] = { 0xFB, 0x3F, 0xF1, 0xF7, 0xCE, 0xD9, 0x16, 0x87, 0x2B },
w28[] = { 0xA2, 0x61, 0x61, 0x01, 0x61, 0x62, 0x82, 0x02, 0x03 },
w29[] = { 0x7F, 0x65, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0xFF
w29[] = { 0x7F, 0x65, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0xFF },
w30[] = { 0xA2, 0x63, 0x67, 0x68, 0x69, 0x18, 0x7B, 0x63, 0x6A, 0x6B, 0x6C, 0x02 },
w31[] = { 0x82, 0x18, 0x81, 0x19, 0x04, 0x00 },
w32[] = { 0xA2, 0x63, 0x67, 0x68, 0x69, 0x38, 0x7A, 0x63, 0x6A, 0x6B, 0x6C, 0x02 },
w33[] = { 0x82, 0x38, 0x80, 0x39, 0x03, 0xFF
}
;
@ -4604,7 +4608,7 @@ int main(int argc, const char **argv)
{
int n, m, e = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE,
expected = (int)LWS_ARRAY_SIZE(cbor_tests) +
29 /* <-- how many write tests */;
33 /* <-- how many write tests */;
struct lecp_ctx ctx;
const char *p;
@ -5000,6 +5004,50 @@ int main(int argc, const char **argv)
e++;
} else
pass++;
lwsl_user("%s: test30\n", __func__);
lws_lec_setbuf(&ctx, buf, sizeof(buf));
if (lws_lec_printf(&ctx, "{'ghi':123,'jkl':2}") !=
LWS_LECPCTX_RET_FINISHED ||
ctx.used != sizeof(w30) || memcmp(w30, buf, ctx.used)) {
lwsl_hexdump_notice(ctx.start, ctx.used);
e++;
} else
pass++;
lwsl_user("%s: test31\n", __func__);
lws_lec_setbuf(&ctx, buf, sizeof(buf));
if (lws_lec_printf(&ctx, "[129,1024]") !=
LWS_LECPCTX_RET_FINISHED ||
ctx.used != sizeof(w31) || memcmp(w31, buf, ctx.used)) {
lwsl_hexdump_notice(ctx.start, ctx.used);
e++;
} else
pass++;
lwsl_user("%s: test32\n", __func__);
lws_lec_setbuf(&ctx, buf, sizeof(buf));
if (lws_lec_printf(&ctx, "{'ghi':-123,'jkl':2}") !=
LWS_LECPCTX_RET_FINISHED ||
ctx.used != sizeof(w32) || memcmp(w32, buf, ctx.used)) {
lwsl_hexdump_notice(ctx.start, ctx.used);
e++;
} else
pass++;
lwsl_user("%s: test33\n", __func__);
lws_lec_setbuf(&ctx, buf, sizeof(buf));
if (lws_lec_printf(&ctx, "[-129,-1024]") !=
LWS_LECPCTX_RET_FINISHED ||
ctx.used != sizeof(w33) || memcmp(w33, buf, ctx.used)) {
lwsl_hexdump_notice(ctx.start, ctx.used);
e++;
} else
pass++;
}
if (e)

View file

@ -127,6 +127,10 @@ static const char * const json_tests[] = {
"{" /* SHOULD_FAIL: test 10, missing open */
"\"a\":123,\"b\":}"
"}",
"{" /* test 13: float vs int */
"\"a\": 1, \"b\": 1.0, \"c\": 1e-3, \"d\": 1e3"
"}"
};

View file

@ -26,7 +26,7 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason,
uint8_t buf[1280];
union lws_tls_cert_info_results *ci =
(union lws_tls_cert_info_results *)buf;
#if defined(LWS_HAVE_CTIME_R)
#if defined(LWS_HAVE_CTIME_R) && !defined(LWS_WITH_NO_LOGS)
char date[32];
#endif

View file

@ -244,6 +244,10 @@ wsi_logical_close_custom(struct lws *wsi)
{
struct pt_eventlibs_custom *priv = (struct pt_eventlibs_custom *)
lws_evlib_wsi_to_evlib_pt(wsi);
if (lws_get_socket_fd(wsi) == LWS_SOCK_INVALID)
return 0;
return custom_poll_del_fd(priv->io_loop, lws_get_socket_fd(wsi));
}

View file

@ -1125,8 +1125,10 @@ pkt_add_hdrs:
goto pkt_add_hdrs;
case ACME_STATE_POLLING_CSR:
if (ac->goes_around)
break;
if (ac->goes_around) {
strcpy(ac->active_url, ac->order_url);
goto pkt_add_hdrs;
}
lwsl_vhost_notice(vhd->vhost, "Generating ACME CSR... may take a little while");
p += lws_snprintf(p, lws_ptr_diff_size_t(end, p), "{\"csr\":\"");
n = lws_tls_acme_sni_csr_create(vhd->context,
@ -1396,7 +1398,7 @@ poll_again:
lws_acme_report_status(vhd->vhost, LWS_CUS_CHALLENGE,
NULL);
if (ac->goes_around++ == 20) {
if (ac->goes_around++ == 200) {
lwsl_notice("%s: too many chall retries\n",
__func__);
@ -1470,13 +1472,13 @@ poll_again:
goto failed;
}
if (ac->resp != 200) {
if (ac->goes_around++ == 30) {
if (ac->resp != 200 || ac->cert_url[0] == '\0') {
if (ac->goes_around++ == 200) {
lwsl_vhost_warn(vhd->vhost, "Too many retries");
goto failed;
}
strcpy(buf, ac->finalize_url);
strcpy(buf, ac->order_url);
cwsi = lws_acme_client_connect(vhd->context,
vhd->vhost,
&ac->cwsi, &ac->i, buf,

View file

@ -163,7 +163,6 @@ if ((LWS_ROLE_H1 OR LWS_ROLE_H2))
set_property(
TARGET test-server-extpoll
PROPERTY COMPILE_DEFINITIONS
LWS_WITH_EXTERNAL_POLL
INSTALL_DATADIR="${CMAKE_INSTALL_PREFIX}/share"
)

View file

@ -720,8 +720,9 @@ int flush;
if (copy > have) copy = have;
if (copy) {
if (state->head != Z_NULL &&
state->head->extra != Z_NULL) {
len = state->head->extra_len - state->length;
state->head->extra != Z_NULL &&
(len = state->head->extra_len - state->length) <
state->head->extra_max) {
zmemcpy(state->head->extra + len, next,
len + copy > state->head->extra_max ?
state->head->extra_max - len : copy);

View file

@ -1,330 +1,328 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#define MAXBITS 15
const char inflate_copyright[] =
" inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
include such an acknowledgment, I would appreciate that you keep this
copyright string in the executable of your product.
*/
/*
Build a set of tables to decode the provided canonical Huffman code.
The code lengths are lens[0..codes-1]. The result starts at *table,
whose indices are 0..2^bits-1. work is a writable array of at least
lens shorts, which is used as a work area. type is the type of code
to be generated, CODES, LENS, or DISTS. On return, zero is success,
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
on return points to the next available entry's address. bits is the
requested root table index bits, and on return it is the actual root
table index bits. It will differ if the request is greater than the
longest code or if it is less than the shortest code.
*/
int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
codetype type;
unsigned short FAR *lens;
unsigned codes;
code FAR * FAR *table;
unsigned FAR *bits;
unsigned short FAR *work;
{
unsigned len; /* a code's length in bits */
unsigned sym; /* index of code symbols */
unsigned min, max; /* minimum and maximum code lengths */
unsigned root; /* number of index bits for root table */
unsigned curr; /* number of index bits for current table */
unsigned drop; /* code bits to drop for sub-table */
int left; /* number of prefix codes available */
unsigned used; /* code entries in table used */
unsigned huff; /* Huffman code */
unsigned incr; /* for incrementing code, index */
unsigned fill; /* index for replicating entries */
unsigned low; /* low bits for current root entry */
unsigned mask; /* mask for low root bits */
code here; /* table entry for duplication */
code FAR *next; /* next available space in table */
const unsigned short FAR *base; /* base value table to use */
const unsigned short FAR *extra; /* extra bits table to use */
int end; /* use base and extra for symbol > end */
unsigned short count[MAXBITS+1]; /* number of codes of each length */
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577, 0, 0};
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
28, 28, 29, 29, 64, 64};
/*
Process a set of code lengths to create a canonical Huffman code. The
code lengths are lens[0..codes-1]. Each length corresponds to the
symbols 0..codes-1. The Huffman code is generated by first sorting the
symbols by length from short to long, and retaining the symbol order
for codes with equal lengths. Then the code starts with all zero bits
for the first code of the shortest length, and the codes are integer
increments for the same length, and zeros are appended as the length
increases. For the deflate format, these bits are stored backwards
from their more natural integer increment ordering, and so when the
decoding tables are built in the large loop below, the integer codes
are incremented backwards.
This routine assumes, but does not check, that all of the entries in
lens[] are in the range 0..MAXBITS. The caller must assure this.
1..MAXBITS is interpreted as that code length. zero means that that
symbol does not occur in this code.
The codes are sorted by computing a count of codes for each length,
creating from that a table of starting indices for each length in the
sorted table, and then entering the symbols in order in the sorted
table. The sorted table is work[], with that space being provided by
the caller.
The length counts are used for other purposes as well, i.e. finding
the minimum and maximum length codes, determining if there are any
codes at all, checking for a valid set of lengths, and looking ahead
at length counts to determine sub-table sizes when building the
decoding tables.
*/
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
for (len = 0; len <= MAXBITS; len++)
count[len] = 0;
for (sym = 0; sym < codes; sym++)
count[lens[sym]]++;
/* bound code lengths, force root to be within code lengths */
root = *bits;
for (max = MAXBITS; max >= 1; max--)
if (count[max] != 0) break;
if (root > max) root = max;
if (max == 0) { /* no symbols to code at all */
here.op = (unsigned char)64; /* invalid code marker */
here.bits = (unsigned char)1;
here.val = (unsigned short)0;
*(*table)++ = here; /* make a table to force an error */
*(*table)++ = here;
*bits = 1;
return 0; /* no symbols, but wait for decoding to report error */
}
for (min = 1; min < max; min++)
if (count[min] != 0) break;
if (root < min) root = min;
/* check for an over-subscribed or incomplete set of lengths */
left = 1;
for (len = 1; len <= MAXBITS; len++) {
left <<= 1;
left -= count[len];
if (left < 0) return -1; /* over-subscribed */
}
if (left > 0 && (type == CODES || max != 1))
return -1; /* incomplete set */
/* generate offsets into symbol table for each length for sorting */
offs[1] = 0;
for (len = 1; len < MAXBITS; len++)
offs[len + 1] = offs[len] + count[len];
/* sort symbols by length, by symbol order within each length */
for (sym = 0; sym < codes; sym++)
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
/*
Create and fill in decoding tables. In this loop, the table being
filled is at next and has curr index bits. The code being used is huff
with length len. That code is converted to an index by dropping drop
bits off of the bottom. For codes where len is less than drop + curr,
those top drop + curr - len bits are incremented through all values to
fill the table with replicated entries.
root is the number of index bits for the root table. When len exceeds
root, sub-tables are created pointed to by the root entry with an index
of the low root bits of huff. This is saved in low to check for when a
new sub-table should be started. drop is zero when the root table is
being filled, and drop is root when sub-tables are being filled.
When a new sub-table is needed, it is necessary to look ahead in the
code lengths to determine what size sub-table is needed. The length
counts are used for this, and so count[] is decremented as codes are
entered in the tables.
used keeps track of how many table entries have been allocated from the
provided *table space. It is checked for LENS and DIST tables against
the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
the initial root table size constants. See the comments in inftrees.h
for more information.
sym increments through all symbols, and the loop terminates when
all codes of length max, i.e. all codes, have been processed. This
routine permits incomplete codes, so another loop after this one fills
in the rest of the decoding tables with invalid code markers.
*/
/* set up for code type */
switch (type) {
case CODES:
base = extra = work; /* dummy value--not used */
end = 19;
break;
case LENS:
base = lbase;
base -= 257;
extra = lext;
extra -= 257;
end = 256;
break;
default: /* DISTS */
base = dbase;
extra = dext;
end = -1;
}
/* initialize state for loop */
huff = 0; /* starting code */
sym = 0; /* starting code symbol */
len = min; /* starting code length */
next = *table; /* current table to fill in */
curr = root; /* current table index bits */
drop = 0; /* current bits to drop from code for index */
low = (unsigned)(-1); /* trigger new sub-table when len > root */
used = 1U << root; /* use root table entries */
mask = used - 1; /* mask for comparing low */
/* check available table space */
if ((type == LENS && used >= ENOUGH_LENS) ||
(type == DISTS && used >= ENOUGH_DISTS))
return 1;
/* process all codes and make table entries */
for (;;) {
/* create table entry */
here.bits = (unsigned char)(len - drop);
if ((int)(work[sym]) < end) {
here.op = (unsigned char)0;
here.val = work[sym];
}
else if ((int)(work[sym]) > end) {
here.op = (unsigned char)(extra[work[sym]]);
here.val = base[work[sym]];
}
else {
here.op = (unsigned char)(32 + 64); /* end of block */
here.val = 0;
}
/* replicate for those indices with low len bits equal to huff */
incr = 1U << (len - drop);
fill = 1U << curr;
min = fill; /* save offset to next table */
do {
fill -= incr;
next[(huff >> drop) + fill] = here;
} while (fill != 0);
/* backwards increment the len-bit code huff */
incr = 1U << (len - 1);
while (huff & incr)
incr >>= 1;
if (incr != 0) {
huff &= incr - 1;
huff += incr;
}
else
huff = 0;
/* go to next symbol, update count, len */
sym++;
if (--(count[len]) == 0) {
if (len == max) break;
len = lens[work[sym]];
}
/* create new sub-table if needed */
if (len > root && (huff & mask) != low) {
/* if first time, transition to sub-tables */
if (drop == 0)
drop = root;
/* increment past last table */
next += min; /* here min is 1 << curr */
/* determine length of next table */
curr = len - drop;
left = (int)(1 << curr);
while (curr + drop < max) {
left -= count[curr + drop];
if (left <= 0) break;
curr++;
left <<= 1;
}
/* check for enough space */
used += 1U << curr;
if ((type == LENS && used >= ENOUGH_LENS) ||
(type == DISTS && used >= ENOUGH_DISTS))
return 1;
/* point entry in root table to sub-table */
low = huff & mask;
(*table)[low].op = (unsigned char)curr;
(*table)[low].bits = (unsigned char)root;
(*table)[low].val = (unsigned short)(next - *table);
}
}
/*
Fill in rest of table for incomplete codes. This loop is similar to the
loop above in incrementing huff for table indices. It is assumed that
len is equal to curr + drop, so there is no loop needed to increment
through high index bits. When the current sub-table is filled, the loop
drops back to the root table to fill in any remaining entries there.
*/
here.op = (unsigned char)64; /* invalid code marker */
here.bits = (unsigned char)(len - drop);
here.val = (unsigned short)0;
while (huff != 0) {
/* when done with sub-table, drop back to root table */
if (drop != 0 && (huff & mask) != low) {
drop = 0;
len = root;
next = *table;
here.bits = (unsigned char)len;
}
/* put invalid code marker in table */
next[huff >> drop] = here;
/* backwards increment the len-bit code huff */
incr = 1U << (len - 1);
while (huff & incr)
incr >>= 1;
if (incr != 0) {
huff &= incr - 1;
huff += incr;
}
else
huff = 0;
}
/* set return parameters */
*table += used;
*bits = root;
return 0;
}
/* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#define MAXBITS 15
const char inflate_copyright[] =
" inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
include such an acknowledgment, I would appreciate that you keep this
copyright string in the executable of your product.
*/
/*
Build a set of tables to decode the provided canonical Huffman code.
The code lengths are lens[0..codes-1]. The result starts at *table,
whose indices are 0..2^bits-1. work is a writable array of at least
lens shorts, which is used as a work area. type is the type of code
to be generated, CODES, LENS, or DISTS. On return, zero is success,
-1 is an invalid code, and +1 means that ENOUGH isn't enough. table
on return points to the next available entry's address. bits is the
requested root table index bits, and on return it is the actual root
table index bits. It will differ if the request is greater than the
longest code or if it is less than the shortest code.
*/
int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work)
codetype type;
unsigned short FAR *lens;
unsigned codes;
code FAR * FAR *table;
unsigned FAR *bits;
unsigned short FAR *work;
{
unsigned len; /* a code's length in bits */
unsigned sym; /* index of code symbols */
unsigned min, max; /* minimum and maximum code lengths */
unsigned root; /* number of index bits for root table */
unsigned curr; /* number of index bits for current table */
unsigned drop; /* code bits to drop for sub-table */
int left; /* number of prefix codes available */
unsigned used; /* code entries in table used */
unsigned huff; /* Huffman code */
unsigned incr; /* for incrementing code, index */
unsigned fill; /* index for replicating entries */
unsigned low; /* low bits for current root entry */
unsigned mask; /* mask for low root bits */
code here; /* table entry for duplication */
code FAR *next; /* next available space in table */
const unsigned short FAR *base; /* base value table to use */
const unsigned short FAR *extra; /* extra bits table to use */
unsigned match; /* use base and extra for symbol >= match */
unsigned short count[MAXBITS+1]; /* number of codes of each length */
unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
static const unsigned short lbase[31] = { /* Length codes 257..285 base */
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
8193, 12289, 16385, 24577, 0, 0};
static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
28, 28, 29, 29, 64, 64};
/*
Process a set of code lengths to create a canonical Huffman code. The
code lengths are lens[0..codes-1]. Each length corresponds to the
symbols 0..codes-1. The Huffman code is generated by first sorting the
symbols by length from short to long, and retaining the symbol order
for codes with equal lengths. Then the code starts with all zero bits
for the first code of the shortest length, and the codes are integer
increments for the same length, and zeros are appended as the length
increases. For the deflate format, these bits are stored backwards
from their more natural integer increment ordering, and so when the
decoding tables are built in the large loop below, the integer codes
are incremented backwards.
This routine assumes, but does not check, that all of the entries in
lens[] are in the range 0..MAXBITS. The caller must assure this.
1..MAXBITS is interpreted as that code length. zero means that that
symbol does not occur in this code.
The codes are sorted by computing a count of codes for each length,
creating from that a table of starting indices for each length in the
sorted table, and then entering the symbols in order in the sorted
table. The sorted table is work[], with that space being provided by
the caller.
The length counts are used for other purposes as well, i.e. finding
the minimum and maximum length codes, determining if there are any
codes at all, checking for a valid set of lengths, and looking ahead
at length counts to determine sub-table sizes when building the
decoding tables.
*/
/* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
for (len = 0; len <= MAXBITS; len++)
count[len] = 0;
for (sym = 0; sym < codes; sym++)
count[lens[sym]]++;
/* bound code lengths, force root to be within code lengths */
root = *bits;
for (max = MAXBITS; max >= 1; max--)
if (count[max] != 0) break;
if (root > max) root = max;
if (max == 0) { /* no symbols to code at all */
here.op = (unsigned char)64; /* invalid code marker */
here.bits = (unsigned char)1;
here.val = (unsigned short)0;
*(*table)++ = here; /* make a table to force an error */
*(*table)++ = here;
*bits = 1;
return 0; /* no symbols, but wait for decoding to report error */
}
for (min = 1; min < max; min++)
if (count[min] != 0) break;
if (root < min) root = min;
/* check for an over-subscribed or incomplete set of lengths */
left = 1;
for (len = 1; len <= MAXBITS; len++) {
left <<= 1;
left -= count[len];
if (left < 0) return -1; /* over-subscribed */
}
if (left > 0 && (type == CODES || max != 1))
return -1; /* incomplete set */
/* generate offsets into symbol table for each length for sorting */
offs[1] = 0;
for (len = 1; len < MAXBITS; len++)
offs[len + 1] = offs[len] + count[len];
/* sort symbols by length, by symbol order within each length */
for (sym = 0; sym < codes; sym++)
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
/*
Create and fill in decoding tables. In this loop, the table being
filled is at next and has curr index bits. The code being used is huff
with length len. That code is converted to an index by dropping drop
bits off of the bottom. For codes where len is less than drop + curr,
those top drop + curr - len bits are incremented through all values to
fill the table with replicated entries.
root is the number of index bits for the root table. When len exceeds
root, sub-tables are created pointed to by the root entry with an index
of the low root bits of huff. This is saved in low to check for when a
new sub-table should be started. drop is zero when the root table is
being filled, and drop is root when sub-tables are being filled.
When a new sub-table is needed, it is necessary to look ahead in the
code lengths to determine what size sub-table is needed. The length
counts are used for this, and so count[] is decremented as codes are
entered in the tables.
used keeps track of how many table entries have been allocated from the
provided *table space. It is checked for LENS and DIST tables against
the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
the initial root table size constants. See the comments in inftrees.h
for more information.
sym increments through all symbols, and the loop terminates when
all codes of length max, i.e. all codes, have been processed. This
routine permits incomplete codes, so another loop after this one fills
in the rest of the decoding tables with invalid code markers.
*/
/* set up for code type */
switch (type) {
case CODES:
base = extra = work; /* dummy value--not used */
match = 20;
break;
case LENS:
base = lbase;
extra = lext;
match = 257;
break;
default: /* DISTS */
base = dbase;
extra = dext;
match = 0;
}
/* initialize state for loop */
huff = 0; /* starting code */
sym = 0; /* starting code symbol */
len = min; /* starting code length */
next = *table; /* current table to fill in */
curr = root; /* current table index bits */
drop = 0; /* current bits to drop from code for index */
low = (unsigned)(-1); /* trigger new sub-table when len > root */
used = 1U << root; /* use root table entries */
mask = used - 1; /* mask for comparing low */
/* check available table space */
if ((type == LENS && used >= ENOUGH_LENS) ||
(type == DISTS && used >= ENOUGH_DISTS))
return 1;
/* process all codes and make table entries */
for (;;) {
/* create table entry */
here.bits = (unsigned char)(len - drop);
if (work[sym] + 1 < match) {
here.op = (unsigned char)0;
here.val = work[sym];
}
else if (work[sym] >= match) {
here.op = (unsigned char)(extra[work[sym] - match]);
here.val = base[work[sym] - match];
}
else {
here.op = (unsigned char)(32 + 64); /* end of block */
here.val = 0;
}
/* replicate for those indices with low len bits equal to huff */
incr = 1U << (len - drop);
fill = 1U << curr;
min = fill; /* save offset to next table */
do {
fill -= incr;
next[(huff >> drop) + fill] = here;
} while (fill != 0);
/* backwards increment the len-bit code huff */
incr = 1U << (len - 1);
while (huff & incr)
incr >>= 1;
if (incr != 0) {
huff &= incr - 1;
huff += incr;
}
else
huff = 0;
/* go to next symbol, update count, len */
sym++;
if (--(count[len]) == 0) {
if (len == max) break;
len = lens[work[sym]];
}
/* create new sub-table if needed */
if (len > root && (huff & mask) != low) {
/* if first time, transition to sub-tables */
if (drop == 0)
drop = root;
/* increment past last table */
next += min; /* here min is 1 << curr */
/* determine length of next table */
curr = len - drop;
left = (int)(1 << curr);
while (curr + drop < max) {
left -= count[curr + drop];
if (left <= 0) break;
curr++;
left <<= 1;
}
/* check for enough space */
used += 1U << curr;
if ((type == LENS && used >= ENOUGH_LENS) ||
(type == DISTS && used >= ENOUGH_DISTS))
return 1;
/* point entry in root table to sub-table */
low = huff & mask;
(*table)[low].op = (unsigned char)curr;
(*table)[low].bits = (unsigned char)root;
(*table)[low].val = (unsigned short)(next - *table);
}
}
/*
Fill in rest of table for incomplete codes. This loop is similar to the
loop above in incrementing huff for table indices. It is assumed that
len is equal to curr + drop, so there is no loop needed to increment
through high index bits. When the current sub-table is filled, the loop
drops back to the root table to fill in any remaining entries there.
*/
here.op = (unsigned char)64; /* invalid code marker */
here.bits = (unsigned char)(len - drop);
here.val = (unsigned short)0;
while (huff != 0) {
/* when done with sub-table, drop back to root table */
if (drop != 0 && (huff & mask) != low) {
drop = 0;
len = root;
next = *table;
here.bits = (unsigned char)len;
}
/* put invalid code marker in table */
next[huff >> drop] = here;
/* backwards increment the len-bit code huff */
incr = 1U << (len - 1);
while (huff & incr)
incr >>= 1;
if (incr != 0) {
huff &= incr - 1;
huff += incr;
}
else
huff = 0;
}
/* set return parameters */
*table += used;
*bits = root;
return 0;
}