Hello community, here is the log from the commit of package haproxy for openSUSE:Factory checked in at 2017-08-24 18:55:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/haproxy (Old) and /work/SRC/openSUSE:Factory/.haproxy.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "haproxy" Thu Aug 24 18:55:41 2017 rev:51 rq:518364 version:1.7.9 Changes: -------- --- /work/SRC/openSUSE:Factory/haproxy/haproxy.changes 2017-08-10 14:11:41.279960693 +0200 +++ /work/SRC/openSUSE:Factory/.haproxy.new/haproxy.changes 2017-08-24 18:56:08.485802338 +0200 @@ -1,0 +2,21 @@ +Wed Aug 23 06:52:05 UTC 2017 - [email protected] + +- Update to version 1.7.9: + * BUG/MINOR: peers: peer synchronization issue (with several peers sections). + * BUG/MINOR: lua: In error case, the safe mode is not removed + * BUG/MINOR: lua: executes the function destroying the Lua session in safe mode + * BUG/MAJOR: lua/socket: resources not detroyed when the socket is aborted + * BUG/MEDIUM: lua: bad memory access + * DOC: update the list of OpenSSL versions in the README + * DOC: Updated 51Degrees git URL to point to a stable version. + * BUG/MINOR: http: Set the response error state in http_sync_res_state + * MINOR: http: Reorder/rewrite checks in http_resync_states + * MINOR: http: Switch requests/responses in TUNNEL mode only by checking txn flags + * BUG/MEDIUM: http: Switch HTTP responses in TUNNEL mode when body length is undefined + * BUG/MAJOR: http: Fix possible infinity loop in http_sync_(req|res)_state + * BUG/MINOR: lua: Fix Server.get_addr() port values + * BUG/MINOR: lua: Correctly use INET6_ADDRSTRLEN in Server.get_addr() + * BUG/MINOR: lua: always detach the tcp/http tasks before freeing them + * BUG/MINOR: lua: Fix bitwise logic for hlua_server_check_* functions. + +------------------------------------------------------------------- Old: ---- haproxy-1.7.8.tar.gz New: ---- haproxy-1.7.9.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ haproxy.spec ++++++ --- /var/tmp/diff_new_pack.VexKgf/_old 2017-08-24 18:56:09.205700972 +0200 +++ /var/tmp/diff_new_pack.VexKgf/_new 2017-08-24 18:56:09.209700409 +0200 @@ -41,7 +41,7 @@ %bcond_without apparmor Name: haproxy -Version: 1.7.8 +Version: 1.7.9 Release: 0 # # ++++++ _service ++++++ --- /var/tmp/diff_new_pack.VexKgf/_old 2017-08-24 18:56:09.265692525 +0200 +++ /var/tmp/diff_new_pack.VexKgf/_new 2017-08-24 18:56:09.269691961 +0200 @@ -3,8 +3,8 @@ <param name="url">http://git.haproxy.org/git/haproxy-1.7.git</param> <param name="scm">git</param> <param name="filename">haproxy</param> - <param name="versionformat">1.7.8</param> - <param name="revision">v1.7.8</param> + <param name="versionformat">1.7.9</param> + <param name="revision">v1.7.9</param> <param name="changesgenerate">enable</param> </service> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.VexKgf/_old 2017-08-24 18:56:09.305686893 +0200 +++ /var/tmp/diff_new_pack.VexKgf/_new 2017-08-24 18:56:09.305686893 +0200 @@ -3,4 +3,4 @@ <param name="url">http://git.haproxy.org/git/haproxy-1.6.git</param> <param name="changesrevision">864bf78c3b6898eb12ece5f0a44032090f26f57f</param></service><service name="tar_scm"> <param name="url">http://git.haproxy.org/git/haproxy-1.7.git</param> - <param name="changesrevision">298376c4a77bae10aa6043cf1f8558001a004064</param></service></servicedata> \ No newline at end of file + <param name="changesrevision">640d526f8cdad00f7f5043b51f6a34f3f6ebb49f</param></service></servicedata> \ No newline at end of file ++++++ haproxy-1.7.8.tar.gz -> haproxy-1.7.9.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/CHANGELOG new/haproxy-1.7.9/CHANGELOG --- old/haproxy-1.7.8/CHANGELOG 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/CHANGELOG 2017-08-18 08:33:20.000000000 +0200 @@ -1,6 +1,27 @@ ChangeLog : =========== +2017/08/18 : 1.7.9 + - BUG/MINOR: peers: peer synchronization issue (with several peers sections). + - BUG/MINOR: lua: In error case, the safe mode is not removed + - BUG/MINOR: lua: executes the function destroying the Lua session in safe mode + - BUG/MAJOR: lua/socket: resources not detroyed when the socket is aborted + - BUG/MEDIUM: lua: bad memory access + - DOC: update CONTRIBUTING regarding optional parts and message format + - DOC: update the list of OpenSSL versions in the README + - MINOR: tools: add a portable timegm() alternative + - BUILD: lua: replace timegm() with my_timegm() to fix build on Solaris 10 + - DOC: Updated 51Degrees git URL to point to a stable version. + - BUG/MINOR: http: Set the response error state in http_sync_res_state + - MINOR: http: Reorder/rewrite checks in http_resync_states + - MINOR: http: Switch requests/responses in TUNNEL mode only by checking txn flags + - BUG/MEDIUM: http: Switch HTTP responses in TUNNEL mode when body length is undefined + - BUG/MAJOR: http: Fix possible infinity loop in http_sync_(req|res)_state + - BUG/MINOR: lua: Fix Server.get_addr() port values + - BUG/MINOR: lua: Correctly use INET6_ADDRSTRLEN in Server.get_addr() + - BUG/MINOR: lua: always detach the tcp/http tasks before freeing them + - BUG/MINOR: lua: Fix bitwise logic for hlua_server_check_* functions. + 2017/07/07 : 1.7.8 - BUG/MINOR: stream: flag TASK_WOKEN_RES not set if task in runqueue - BUG/MAJOR: cli: fix custom io_release was crushed by NULL. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/CONTRIBUTING new/haproxy-1.7.9/CONTRIBUTING --- old/haproxy-1.7.8/CONTRIBUTING 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/CONTRIBUTING 2017-08-18 08:33:20.000000000 +0200 @@ -69,6 +69,16 @@ Since most of these restrictions are just a matter of coding style, it is normally not a problem to comply. +When modifying some optional subsystem (SSL, Lua, compression, device detection +engines), please make sure the code continues to build (and to work) when these +features are disabled. Similarly, when modifying the SSL stack, please always +ensure that supported OpenSSL versions continue to build and to work, especially +if you modify support for alternate libraries. Clean support for the legacy +OpenSSL libraries is mandatory, support for its derivatives is a bonus and may +occasionally break eventhough a great care is taken. In other words, if you +provide a patch for OpenSSL you don't need to test its derivatives, but if you +provide a patch for a derivative you also need to test with OpenSSL. + If your work is very confidential and you can't publicly discuss it, you can also mail [email protected] directly about it, but your mail may be waiting several days in the queue before you get a response, if you get a response at @@ -441,13 +451,22 @@ way the subject is built. Please see the section below for more information regarding this formatting. - As a rule of thumb, your patch must never be made only of a subject line, + As a rule of thumb, your patch MUST NEVER be made only of a subject line, it *must* contain a description. Even one or two lines, or indicating whether a backport is desired or not. It turns out that single-line commits are so rare in the Git world that they require special manual (hence painful) handling when they are backported, and at least for this reason it's important to keep this in mind. + Each patch fixing a bug MUST be tagged with "BUG", a severity level, an + indication of the affected subsystem and a brief description of the nature + of the issue in the subject line, and a detailed analysis in the message + body. The explanation of the user-visible impact and the need for + backporting to stable branches or not are MANDATORY. Bug fixes with no + indication will simply be rejected as they are very likely to cause more + harm when nobody is able to tell whether or not the patch needs to be + backported or can be reverted in case of regression. + 12) Discuss on the mailing list When submitting changes, please always CC the mailing list address so that diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/README new/haproxy-1.7.9/README --- old/haproxy-1.7.8/README 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/README 2017-08-18 08:33:20.000000000 +0200 @@ -3,7 +3,7 @@ ---------------------- version 1.7 willy tarreau - 2017/07/07 + 2017/08/18 1) How to build it @@ -113,8 +113,12 @@ Your are strongly encouraged to always use an up-to-date version of OpenSSL, as found on https://www.openssl.org/ as vulnerabilities are occasionally found and you don't want them on your systems. HAProxy is known to build correctly on all -currently supported branches (0.9.8, 1.0.0, 1.0.1 and 1.0.2 at the time of -writing). Branch 1.0.2 is recommended for the richest features. +currently supported branches (0.9.8, 1.0.0, 1.0.1, 1.0.2 and 1.1.0 at the time +of writing). Branch 1.0.2 is currently recommended for the best combination of +features and stability. Asynchronous engines require OpenSSL 1.1.0 though. It's +worth mentionning that some OpenSSL derivatives are also reported to work but +may occasionally break. Patches to fix them are welcome but please read the +CONTRIBUTING file first. To link OpenSSL statically against haproxy, build OpenSSL with the no-shared keyword and install it to a local directory, so your system is not affected : diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/VERDATE new/haproxy-1.7.9/VERDATE --- old/haproxy-1.7.8/VERDATE 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/VERDATE 2017-08-18 08:33:20.000000000 +0200 @@ -1,2 +1,2 @@ $Format:%ci$ -2017/07/07 +2017/08/18 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/VERSION new/haproxy-1.7.9/VERSION --- old/haproxy-1.7.8/VERSION 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/VERSION 2017-08-18 08:33:20.000000000 +0200 @@ -1 +1 @@ -1.7.8 +1.7.9 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/doc/51Degrees-device-detection.txt new/haproxy-1.7.9/doc/51Degrees-device-detection.txt --- old/haproxy-1.7.8/doc/51Degrees-device-detection.txt 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/doc/51Degrees-device-detection.txt 2017-08-18 08:33:20.000000000 +0200 @@ -14,7 +14,7 @@ In order to enable 51Degrees download the 51Degrees source code from the official github repository : - git clone https://github.com/51Degrees/Device-Detection + git clone https://git.51Degrees.com/Device-Detection.git -b v3.2.10 then run 'make' with USE_51DEGREES and 51DEGREES_SRC set. Both 51DEGREES_INC and 51DEGREES_LIB may additionally be used to force specific different paths diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/doc/configuration.txt new/haproxy-1.7.9/doc/configuration.txt --- old/haproxy-1.7.8/doc/configuration.txt 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/doc/configuration.txt 2017-08-18 08:33:20.000000000 +0200 @@ -4,7 +4,7 @@ ---------------------- version 1.7 willy tarreau - 2017/07/07 + 2017/08/18 This document covers the configuration language as implemented in the version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/examples/haproxy.spec new/haproxy-1.7.9/examples/haproxy.spec --- old/haproxy-1.7.8/examples/haproxy.spec 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/examples/haproxy.spec 2017-08-18 08:33:20.000000000 +0200 @@ -1,6 +1,6 @@ Summary: HA-Proxy is a TCP/HTTP reverse proxy for high availability environments Name: haproxy -Version: 1.7.8 +Version: 1.7.9 Release: 1 License: GPL Group: System Environment/Daemons @@ -74,6 +74,9 @@ %attr(0755,root,root) %config %{_sysconfdir}/rc.d/init.d/%{name} %changelog +* Fri Aug 18 2017 William Lallemand <[email protected]> +- updated to 1.7.9 + * Fri Jul 7 2017 William Lallemand <[email protected]> - updated to 1.7.8 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/include/common/standard.h new/haproxy-1.7.9/include/common/standard.h --- old/haproxy-1.7.8/include/common/standard.h 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/include/common/standard.h 2017-08-18 08:33:20.000000000 +0200 @@ -624,6 +624,27 @@ gmtime_r(&now, tm); } +/* Counts a number of elapsed days since 01/01/0000 based solely on elapsed + * years and assuming the regular rule for leap years applies. It's fake but + * serves as a temporary origin. It's worth remembering that it's the first + * year of each period that is leap and not the last one, so for instance year + * 1 sees 366 days since year 0 was leap. For this reason we have to apply + * modular arithmetics which is why we offset the year by 399 before + * subtracting the excess at the end. No overflow here before ~11.7 million + * years. + */ +static inline unsigned int days_since_zero(unsigned int y) +{ + return y * 365 + (y + 399) / 4 - (y + 399) / 100 + (y + 399) / 400 + - 399 / 4 + 399 / 100; +} + +/* Returns the number of seconds since 01/01/1970 0:0:0 GMT for GMT date <tm>. + * It is meant as a portable replacement for timegm() for use with valid inputs. + * Returns undefined results for invalid dates (eg: months out of range 0..11). + */ +extern time_t my_timegm(const struct tm *tm); + /* This function parses a time value optionally followed by a unit suffix among * "d", "h", "m", "s", "ms" or "us". It converts the value into the unit * expected by the caller. The computation does its best to avoid overflows. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/include/types/applet.h new/haproxy-1.7.9/include/types/applet.h --- old/haproxy-1.7.8/include/types/applet.h 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/include/types/applet.h 2017-08-18 08:33:20.000000000 +0200 @@ -122,6 +122,7 @@ struct hlua_socket *socket; struct list wake_on_read; struct list wake_on_write; + int die; } hlua; struct { struct hlua hlua; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/include/types/peers.h new/haproxy-1.7.9/include/types/peers.h --- old/haproxy-1.7.8/include/types/peers.h 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/include/types/peers.h 2017-08-18 08:33:20.000000000 +0200 @@ -91,7 +91,7 @@ }; -extern struct peers *peers; +extern struct peers *cfg_peers; #endif /* _TYPES_PEERS_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/src/cfgparse.c new/haproxy-1.7.9/src/cfgparse.c --- old/haproxy-1.7.8/src/cfgparse.c 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/src/cfgparse.c 2017-08-18 08:33:20.000000000 +0200 @@ -2124,7 +2124,7 @@ goto out; } - for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) { + for (curpeers = cfg_peers; curpeers != NULL; curpeers = curpeers->next) { /* * If there are two proxies with the same name only following * combinations are allowed: @@ -2142,8 +2142,8 @@ goto out; } - curpeers->next = peers; - peers = curpeers; + curpeers->next = cfg_peers; + cfg_peers = curpeers; curpeers->conf.file = strdup(file); curpeers->conf.line = linenum; curpeers->last_change = now.tv_sec; @@ -2223,7 +2223,7 @@ if (strcmp(newpeer->id, localpeer) == 0) { /* Current is local peer, it define a frontend */ newpeer->local = 1; - peers->local = newpeer; + cfg_peers->local = newpeer; if (!curpeers->peers_fe) { if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) { @@ -8189,9 +8189,9 @@ } if (curproxy->table.peers.name) { - struct peers *curpeers = peers; + struct peers *curpeers; - for (curpeers = peers; curpeers; curpeers = curpeers->next) { + for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) { if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) { free((void *)curproxy->table.peers.name); curproxy->table.peers.p = curpeers; @@ -9279,15 +9279,15 @@ if (curproxy->table.peers.p) curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc; - if (peers) { - struct peers *curpeers = peers, **last; + if (cfg_peers) { + struct peers *curpeers = cfg_peers, **last; struct peer *p, *pb; /* Remove all peers sections which don't have a valid listener, * which are not used by any table, or which are bound to more * than one process. */ - last = &peers; + last = &cfg_peers; while (*last) { curpeers = *last; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/src/haproxy.c new/haproxy-1.7.9/src/haproxy.c --- old/haproxy-1.7.8/src/haproxy.c 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/src/haproxy.c 2017-08-18 08:33:20.000000000 +0200 @@ -988,7 +988,7 @@ struct peers *pr; struct proxy *px; - for (pr = peers; pr; pr = pr->next) + for (pr = cfg_peers; pr; pr = pr->next) if (pr->peers_fe) break; @@ -1217,11 +1217,11 @@ if (global.stats_fe) global.maxsock += global.stats_fe->maxconn; - if (peers) { + if (cfg_peers) { /* peers also need to bypass global maxconn */ - struct peers *p = peers; + struct peers *p = cfg_peers; - for (p = peers; p; p = p->next) + for (p = cfg_peers; p; p = p->next) if (p->peers_fe) global.maxsock += p->peers_fe->maxconn; } @@ -2067,7 +2067,7 @@ } /* we might have to unbind some peers sections from some processes */ - for (curpeers = peers; curpeers; curpeers = curpeers->next) { + for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) { if (!curpeers->peers_fe) continue; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/src/hlua.c new/haproxy-1.7.9/src/hlua.c --- old/haproxy-1.7.8/src/hlua.c 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/src/hlua.c 2017-08-18 08:33:20.000000000 +0200 @@ -854,6 +854,7 @@ lua->T = lua_newthread(gL.T); if (!lua->T) { lua->Tref = LUA_REFNIL; + RESET_SAFE_LJMP(gL.T); return 0; } hlua_sethlua(lua); @@ -875,9 +876,15 @@ /* Purge all the pending signals. */ hlua_com_purge(lua); + if (!SET_SAFE_LJMP(lua->T)) + return; luaL_unref(lua->T, LUA_REGISTRYINDEX, lua->Mref); - luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref); + RESET_SAFE_LJMP(lua->T); + if (!SET_SAFE_LJMP(gL.T)) + return; + luaL_unref(gL.T, LUA_REGISTRYINDEX, lua->Tref); + RESET_SAFE_LJMP(gL.T); /* Forces a garbage collecting process. If the Lua program is finished * without error, we run the GC on the thread pointer. Its freed all * the unused memory. @@ -888,9 +895,10 @@ * the garbage collection. */ if (lua->flags & HLUA_MUST_GC) { - lua_gc(lua->T, LUA_GCCOLLECT, 0); - if (lua_status(lua->T) != LUA_OK) - lua_gc(gL.T, LUA_GCCOLLECT, 0); + if (!SET_SAFE_LJMP(gL.T)) + return; + lua_gc(gL.T, LUA_GCCOLLECT, 0); + RESET_SAFE_LJMP(gL.T); } lua->T = NULL; @@ -1530,6 +1538,15 @@ struct stream_interface *si = appctx->owner; struct connection *c = objt_conn(si_opposite(si)->end); + if (appctx->ctx.hlua.die) { + si_shutw(si); + si_shutr(si); + si_ic(si)->flags |= CF_READ_NULL; + hlua_com_wake(&appctx->ctx.hlua.wake_on_read); + hlua_com_wake(&appctx->ctx.hlua.wake_on_write); + stream_shutdown(si_strm(si), SF_ERR_KILLED); + } + /* If the connection object is not avalaible, close all the * streams and wakeup everithing waiting for. */ @@ -1605,9 +1622,10 @@ /* Remove all reference between the Lua stack and the coroutine stream. */ appctx = objt_appctx(socket->s->si[0].end); - stream_shutdown(socket->s, SF_ERR_KILLED); socket->s = NULL; appctx->ctx.hlua.socket = NULL; + appctx->ctx.hlua.die = 1; + appctx_wakeup(appctx); return 0; } @@ -1627,10 +1645,11 @@ return 0; /* Close the stream and remove the associated stop task. */ - stream_shutdown(socket->s, SF_ERR_KILLED); appctx = objt_appctx(socket->s->si[0].end); appctx->ctx.hlua.socket = NULL; socket->s = NULL; + appctx->ctx.hlua.die = 1; + appctx_wakeup(appctx); return 0; } @@ -2302,6 +2321,7 @@ appctx->ctx.hlua.socket = socket; appctx->ctx.hlua.connected = 0; + appctx->ctx.hlua.die = 0; LIST_INIT(&appctx->ctx.hlua.wake_on_write); LIST_INIT(&appctx->ctx.hlua.wake_on_read); @@ -5928,6 +5948,7 @@ static void hlua_applet_tcp_release(struct appctx *ctx) { + task_delete(ctx->ctx.hlua_apptcp.task); task_free(ctx->ctx.hlua_apptcp.task); ctx->ctx.hlua_apptcp.task = NULL; hlua_ctx_destroy(&ctx->ctx.hlua_apptcp.hlua); @@ -6206,6 +6227,7 @@ static void hlua_applet_http_release(struct appctx *ctx) { + task_delete(ctx->ctx.hlua_apphttp.task); task_free(ctx->ctx.hlua_apphttp.task); ctx->ctx.hlua_apphttp.task = NULL; hlua_ctx_destroy(&ctx->ctx.hlua_apphttp.hlua); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/src/hlua_fcn.c new/haproxy-1.7.9/src/hlua_fcn.c --- old/haproxy-1.7.8/src/hlua_fcn.c 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/src/hlua_fcn.c 2017-08-18 08:33:20.000000000 +0200 @@ -287,7 +287,7 @@ * the timezone from the broken-down time, it must be fixed * after the conversion. */ - time = timegm(&tm); + time = my_timegm(&tm); if (time == -1) { lua_pushnil(L); return 1; @@ -545,17 +545,15 @@ addr, INET_ADDRSTRLEN); luaL_addstring(&b, addr); luaL_addstring(&b, ":"); - snprintf(addr, INET_ADDRSTRLEN, "%d", - ntohs(((struct sockaddr_in *)&srv->addr)->sin_port)); + snprintf(addr, INET_ADDRSTRLEN, "%d", srv->svc_port); luaL_addstring(&b, addr); break; case AF_INET6: inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&srv->addr)->sin6_addr, - addr, INET_ADDRSTRLEN); + addr, INET6_ADDRSTRLEN); luaL_addstring(&b, addr); luaL_addstring(&b, ":"); - snprintf(addr, INET_ADDRSTRLEN, "%d", - ntohs(((struct sockaddr_in6 *)&srv->addr)->sin6_port)); + snprintf(addr, INET_ADDRSTRLEN, "%d", srv->svc_port); luaL_addstring(&b, addr); break; case AF_UNIX: @@ -664,7 +662,7 @@ sv = hlua_check_server(L, 1); if (sv->check.state & CHK_ST_CONFIGURED) { - sv->check.state &= ~CHK_ST_ENABLED; + sv->check.state |= CHK_ST_ENABLED; } return 0; } @@ -675,7 +673,7 @@ sv = hlua_check_server(L, 1); if (sv->check.state & CHK_ST_CONFIGURED) { - sv->check.state |= CHK_ST_ENABLED; + sv->check.state &= ~CHK_ST_ENABLED; } return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/src/peers.c new/haproxy-1.7.9/src/peers.c --- old/haproxy-1.7.8/src/peers.c 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/src/peers.c 2017-08-18 08:33:20.000000000 +0200 @@ -171,7 +171,7 @@ #define PEER_MINOR_VER 1 #define PEER_DWNGRD_MINOR_VER 0 -struct peers *peers = NULL; +struct peers *cfg_peers = NULL; static void peer_session_forceshutdown(struct appctx *appctx); /* This function encode an uint64 to 'dynamic' length format. @@ -727,19 +727,19 @@ /* if current peer is local */ if (curpeer->local) { /* if current host need resyncfrom local and no process assined */ - if ((peers->flags & PEERS_RESYNC_STATEMASK) == PEERS_RESYNC_FROMLOCAL && - !(peers->flags & PEERS_F_RESYNC_ASSIGN)) { + if ((curpeers->flags & PEERS_RESYNC_STATEMASK) == PEERS_RESYNC_FROMLOCAL && + !(curpeers->flags & PEERS_F_RESYNC_ASSIGN)) { /* assign local peer for a lesson, consider lesson already requested */ curpeer->flags |= PEER_F_LEARN_ASSIGN; - peers->flags |= (PEERS_F_RESYNC_ASSIGN|PEERS_F_RESYNC_PROCESS); + curpeers->flags |= (PEERS_F_RESYNC_ASSIGN|PEERS_F_RESYNC_PROCESS); } } - else if ((peers->flags & PEERS_RESYNC_STATEMASK) == PEERS_RESYNC_FROMREMOTE && - !(peers->flags & PEERS_F_RESYNC_ASSIGN)) { + else if ((curpeers->flags & PEERS_RESYNC_STATEMASK) == PEERS_RESYNC_FROMREMOTE && + !(curpeers->flags & PEERS_F_RESYNC_ASSIGN)) { /* assign peer for a lesson */ curpeer->flags |= PEER_F_LEARN_ASSIGN; - peers->flags |= PEERS_F_RESYNC_ASSIGN; + curpeers->flags |= PEERS_F_RESYNC_ASSIGN; } @@ -807,7 +807,7 @@ curpeer->statuscode = atoi(trash.str); /* Awake main task */ - task_wakeup(peers->sync_task, TASK_WOKEN_MSG); + task_wakeup(curpeers->sync_task, TASK_WOKEN_MSG); /* If status code is success */ if (curpeer->statuscode == PEER_SESS_SC_SUCCESSCODE) { @@ -830,14 +830,14 @@ curpeer->flags |= PEER_F_TEACH_PROCESS; } - else if ((peers->flags & PEERS_RESYNC_STATEMASK) == PEERS_RESYNC_FROMREMOTE && - !(peers->flags & PEERS_F_RESYNC_ASSIGN)) { + else if ((curpeers->flags & PEERS_RESYNC_STATEMASK) == PEERS_RESYNC_FROMREMOTE && + !(curpeers->flags & PEERS_F_RESYNC_ASSIGN)) { /* If peer is remote and resync from remote is needed, and no peer currently assigned */ /* assign peer for a lesson */ curpeer->flags |= PEER_F_LEARN_ASSIGN; - peers->flags |= PEERS_F_RESYNC_ASSIGN; + curpeers->flags |= PEERS_F_RESYNC_ASSIGN; } } @@ -950,8 +950,8 @@ if (curpeer->flags & PEER_F_LEARN_ASSIGN) { curpeer->flags &= ~PEER_F_LEARN_ASSIGN; - peers->flags &= ~(PEERS_F_RESYNC_ASSIGN|PEERS_F_RESYNC_PROCESS); - peers->flags |= (PEERS_F_RESYNC_LOCAL|PEERS_F_RESYNC_REMOTE); + curpeers->flags &= ~(PEERS_F_RESYNC_ASSIGN|PEERS_F_RESYNC_PROCESS); + curpeers->flags |= (PEERS_F_RESYNC_LOCAL|PEERS_F_RESYNC_REMOTE); } curpeer->confirm++; } @@ -959,11 +959,11 @@ if (curpeer->flags & PEER_F_LEARN_ASSIGN) { curpeer->flags &= ~PEER_F_LEARN_ASSIGN; - peers->flags &= ~(PEERS_F_RESYNC_ASSIGN|PEERS_F_RESYNC_PROCESS); + curpeers->flags &= ~(PEERS_F_RESYNC_ASSIGN|PEERS_F_RESYNC_PROCESS); curpeer->flags |= PEER_F_LEARN_NOTUP2DATE; - peers->resync_timeout = tick_add(now_ms, MS_TO_TICKS(5000)); - task_wakeup(peers->sync_task, TASK_WOKEN_MSG); + curpeers->resync_timeout = tick_add(now_ms, MS_TO_TICKS(5000)); + task_wakeup(curpeers->sync_task, TASK_WOKEN_MSG); } curpeer->confirm++; } @@ -1334,8 +1334,8 @@ /* Need to request a resync */ if ((curpeer->flags & PEER_F_LEARN_ASSIGN) && - (peers->flags & PEERS_F_RESYNC_ASSIGN) && - !(peers->flags & PEERS_F_RESYNC_PROCESS)) { + (curpeers->flags & PEERS_F_RESYNC_ASSIGN) && + !(curpeers->flags & PEERS_F_RESYNC_PROCESS)) { unsigned char msg[2]; /* Current peer was elected to request a resync */ @@ -1351,7 +1351,7 @@ appctx->st0 = PEER_SESS_ST_END; goto switchstate; } - peers->flags |= PEERS_F_RESYNC_PROCESS; + curpeers->flags |= PEERS_F_RESYNC_PROCESS; } /* Nothing to read, now we start to write */ @@ -1624,7 +1624,7 @@ /* Current peer was elected to request a resync */ msg[0] = PEER_MSG_CLASS_CONTROL; - msg[1] = ((peers->flags & PEERS_RESYNC_STATEMASK) == PEERS_RESYNC_FINISHED) ? PEER_MSG_CTRL_RESYNCFINISHED : PEER_MSG_CTRL_RESYNCPARTIAL; + msg[1] = ((curpeers->flags & PEERS_RESYNC_STATEMASK) == PEERS_RESYNC_FINISHED) ? PEER_MSG_CTRL_RESYNCFINISHED : PEER_MSG_CTRL_RESYNCPARTIAL; /* process final lesson message */ repl = bi_putblk(si_ic(si), (char *)msg, sizeof(msg)); if (repl <= 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/src/proto_http.c new/haproxy-1.7.9/src/proto_http.c --- old/haproxy-1.7.8/src/proto_http.c 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/src/proto_http.c 2017-08-18 08:33:20.000000000 +0200 @@ -5294,7 +5294,7 @@ unsigned int old_flags = chn->flags; unsigned int old_state = txn->req.msg_state; - if (unlikely(txn->req.msg_state < HTTP_MSG_BODY)) + if (unlikely(txn->req.msg_state < HTTP_MSG_DONE)) return 0; if (txn->req.msg_state == HTTP_MSG_DONE) { @@ -5338,13 +5338,6 @@ goto wait_other_side; } - if (txn->rsp.msg_state == HTTP_MSG_TUNNEL) { - /* if any side switches to tunnel mode, the other one does too */ - channel_auto_read(chn); - txn->req.msg_state = HTTP_MSG_TUNNEL; - goto wait_other_side; - } - /* When we get here, it means that both the request and the * response have finished receiving. Depending on the connection * mode, we'll have to wait for the last bytes to leave in either @@ -5361,7 +5354,16 @@ * let's enforce it now that we're not expecting any new * data to come. The caller knows the stream is complete * once both states are CLOSED. + * + * However, there is an exception if the response + * length is undefined. In this case, we need to wait + * the close from the server. The response will be + * switched in TUNNEL mode until the end. */ + if (!(txn->rsp.flags & HTTP_MSGF_XFER_LEN) && + txn->rsp.msg_state != HTTP_MSG_CLOSED) + goto check_channel_flags; + if (!(chn->flags & (CF_SHUTW|CF_SHUTW_NOW))) { channel_shutr_now(chn); channel_shutw_now(chn); @@ -5377,20 +5379,7 @@ } } - if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW)) { - /* if we've just closed an output, let's switch */ - s->si[1].flags |= SI_FL_NOLINGER; /* we want to close ASAP */ - - if (!channel_is_empty(chn)) { - txn->req.msg_state = HTTP_MSG_CLOSING; - goto http_msg_closing; - } - else { - txn->req.msg_state = HTTP_MSG_CLOSED; - goto http_msg_closed; - } - } - goto wait_other_side; + goto check_channel_flags; } if (txn->req.msg_state == HTTP_MSG_CLOSING) { @@ -5405,8 +5394,8 @@ else if (chn->flags & CF_SHUTW) { txn->req.err_state = txn->req.msg_state; txn->req.msg_state = HTTP_MSG_ERROR; - goto wait_other_side; } + goto wait_other_side; } if (txn->req.msg_state == HTTP_MSG_CLOSED) { @@ -5419,6 +5408,16 @@ goto wait_other_side; } + check_channel_flags: + /* Here, we are in HTTP_MSG_DONE or HTTP_MSG_TUNNEL */ + if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW)) { + /* if we've just closed an output, let's switch */ + s->si[1].flags |= SI_FL_NOLINGER; /* we want to close ASAP */ + txn->req.msg_state = HTTP_MSG_CLOSING; + goto http_msg_closing; + } + + wait_other_side: return txn->req.msg_state != old_state || chn->flags != old_flags; } @@ -5438,7 +5437,7 @@ unsigned int old_flags = chn->flags; unsigned int old_state = txn->rsp.msg_state; - if (unlikely(txn->rsp.msg_state < HTTP_MSG_BODY)) + if (unlikely(txn->rsp.msg_state < HTTP_MSG_DONE)) return 0; if (txn->rsp.msg_state == HTTP_MSG_DONE) { @@ -5461,14 +5460,6 @@ goto wait_other_side; } - if (txn->req.msg_state == HTTP_MSG_TUNNEL) { - /* if any side switches to tunnel mode, the other one does too */ - channel_auto_read(chn); - txn->rsp.msg_state = HTTP_MSG_TUNNEL; - chn->flags |= CF_NEVER_WAIT; - goto wait_other_side; - } - /* When we get here, it means that both the request and the * response have finished receiving. Depending on the connection * mode, we'll have to wait for the last bytes to leave in either @@ -5489,8 +5480,16 @@ * let's enforce it now that we're not expecting any new * data to come. The caller knows the stream is complete * once both states are CLOSED. + * + * However, there is an exception if the response length + * is undefined. In this case, we switch in TUNNEL mode. */ - if (!(chn->flags & (CF_SHUTW|CF_SHUTW_NOW))) { + if (!(txn->rsp.flags & HTTP_MSGF_XFER_LEN)) { + channel_auto_read(chn); + txn->rsp.msg_state = HTTP_MSG_TUNNEL; + chn->flags |= CF_NEVER_WAIT; + } + else if (!(chn->flags & (CF_SHUTW|CF_SHUTW_NOW))) { channel_shutr_now(chn); channel_shutw_now(chn); } @@ -5506,18 +5505,7 @@ txn->rsp.msg_state = HTTP_MSG_TUNNEL; } - if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW)) { - /* if we've just closed an output, let's switch */ - if (!channel_is_empty(chn)) { - txn->rsp.msg_state = HTTP_MSG_CLOSING; - goto http_msg_closing; - } - else { - txn->rsp.msg_state = HTTP_MSG_CLOSED; - goto http_msg_closed; - } - } - goto wait_other_side; + goto check_channel_flags; } if (txn->rsp.msg_state == HTTP_MSG_CLOSING) { @@ -5530,13 +5518,13 @@ goto http_msg_closed; } else if (chn->flags & CF_SHUTW) { - txn->req.err_state = txn->req.msg_state; + txn->rsp.err_state = txn->rsp.msg_state; txn->rsp.msg_state = HTTP_MSG_ERROR; s->be->be_counters.cli_aborts++; if (objt_server(s->target)) objt_server(s->target)->counters.cli_aborts++; - goto wait_other_side; } + goto wait_other_side; } if (txn->rsp.msg_state == HTTP_MSG_CLOSED) { @@ -5548,6 +5536,14 @@ goto wait_other_side; } + check_channel_flags: + /* Here, we are in HTTP_MSG_DONE or HTTP_MSG_TUNNEL */ + if (chn->flags & (CF_SHUTW|CF_SHUTW_NOW)) { + /* if we've just closed an output, let's switch */ + txn->rsp.msg_state = HTTP_MSG_CLOSING; + goto http_msg_closing; + } + wait_other_side: /* We force the response to leave immediately if we're waiting for the * other side, since there is no pending shutdown to push it out. @@ -5577,34 +5573,27 @@ /* OK, both state machines agree on a compatible state. * There are a few cases we're interested in : - * - HTTP_MSG_TUNNEL on either means we have to disable both analysers * - HTTP_MSG_CLOSED on both sides means we've reached the end in both * directions, so let's simply disable both analysers. - * - HTTP_MSG_CLOSED on the response only means we must abort the - * request. - * - HTTP_MSG_CLOSED on the request and HTTP_MSG_DONE on the response - * with server-close mode means we've completed one request and we - * must re-initialize the server connection. + * - HTTP_MSG_CLOSED on the response only or HTTP_MSG_ERROR on either + * means we must abort the request. + * - HTTP_MSG_TUNNEL on either means we have to disable analyser on + * corresponding channel. + * - HTTP_MSG_DONE or HTTP_MSG_CLOSED on the request and HTTP_MSG_DONE + * on the response with server-close mode means we've completed one + * request and we must re-initialize the server connection. */ - - if (txn->req.msg_state == HTTP_MSG_TUNNEL || - txn->rsp.msg_state == HTTP_MSG_TUNNEL || - (txn->req.msg_state == HTTP_MSG_CLOSED && - txn->rsp.msg_state == HTTP_MSG_CLOSED)) { + if (txn->req.msg_state == HTTP_MSG_CLOSED && + txn->rsp.msg_state == HTTP_MSG_CLOSED) { s->req.analysers &= AN_REQ_FLT_END; channel_auto_close(&s->req); channel_auto_read(&s->req); s->res.analysers &= AN_RES_FLT_END; channel_auto_close(&s->res); channel_auto_read(&s->res); - if (txn->req.msg_state == HTTP_MSG_TUNNEL && HAS_REQ_DATA_FILTERS(s)) - s->req.analysers |= AN_REQ_FLT_XFER_DATA; - if (txn->rsp.msg_state == HTTP_MSG_TUNNEL && HAS_RSP_DATA_FILTERS(s)) - s->res.analysers |= AN_RES_FLT_XFER_DATA; - } - else if ((txn->req.msg_state >= HTTP_MSG_DONE && - (txn->rsp.msg_state == HTTP_MSG_CLOSED || (s->res.flags & CF_SHUTW))) || - txn->rsp.msg_state == HTTP_MSG_ERROR || + } + else if (txn->rsp.msg_state == HTTP_MSG_CLOSED || + txn->rsp.msg_state == HTTP_MSG_ERROR || txn->req.msg_state == HTTP_MSG_ERROR) { s->res.analysers &= AN_RES_FLT_END; channel_auto_close(&s->res); @@ -5615,6 +5604,23 @@ channel_auto_read(&s->req); channel_truncate(&s->req); } + else if (txn->req.msg_state == HTTP_MSG_TUNNEL || + txn->rsp.msg_state == HTTP_MSG_TUNNEL) { + if (txn->req.msg_state == HTTP_MSG_TUNNEL) { + s->req.analysers &= AN_REQ_FLT_END; + if (HAS_REQ_DATA_FILTERS(s)) + s->req.analysers |= AN_REQ_FLT_XFER_DATA; + } + if (txn->rsp.msg_state == HTTP_MSG_TUNNEL) { + s->res.analysers &= AN_RES_FLT_END; + if (HAS_RSP_DATA_FILTERS(s)) + s->res.analysers |= AN_RES_FLT_XFER_DATA; + } + channel_auto_close(&s->req); + channel_auto_read(&s->req); + channel_auto_close(&s->res); + channel_auto_read(&s->res); + } else if ((txn->req.msg_state == HTTP_MSG_DONE || txn->req.msg_state == HTTP_MSG_CLOSED) && txn->rsp.msg_state == HTTP_MSG_DONE && @@ -6963,14 +6969,6 @@ if ((msg->flags & HTTP_MSGF_TE_CHNK) || (msg->flags & HTTP_MSGF_COMPRESSING)) res->flags |= CF_EXPECT_MORE; - /* If there is neither content-length, nor transfer-encoding header - * _AND_ there is no data filtering, we can safely forward all data - * indefinitely. */ - if (!(msg->flags & HTTP_MSGF_XFER_LEN) && !HAS_DATA_FILTERS(s, res)) { - buffer_flush(res->buf); - channel_forward_forever(res); - } - /* the stream handler will take care of timeouts and errors */ return 0; @@ -7047,9 +7045,13 @@ goto missing_data_or_waiting; } - /* The server still sending data that should be filtered */ - if (!(msg->flags & HTTP_MSGF_XFER_LEN) && !(chn->flags & CF_SHUTR)) - goto missing_data_or_waiting; + /* This check can only be true for a response. HTTP_MSGF_XFER_LEN is + * always set for a request. */ + if (!(msg->flags & HTTP_MSGF_XFER_LEN)) { + /* The server still sending data that should be filtered */ + if (!(chn->flags & CF_SHUTR) && HAS_DATA_FILTERS(s, chn)) + goto missing_data_or_waiting; + } msg->msg_state = HTTP_MSG_ENDING; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/src/proxy.c new/haproxy-1.7.9/src/proxy.c --- old/haproxy-1.7.8/src/proxy.c 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/src/proxy.c 2017-08-18 08:33:20.000000000 +0200 @@ -1007,7 +1007,7 @@ p = p->next; } - prs = peers; + prs = cfg_peers; while (prs) { if (prs->peers_fe) stop_proxy(prs->peers_fe); @@ -1142,7 +1142,7 @@ p = p->next; } - prs = peers; + prs = cfg_peers; while (prs) { if (prs->peers_fe) err |= !pause_proxy(prs->peers_fe); @@ -1176,7 +1176,7 @@ p = p->next; } - prs = peers; + prs = cfg_peers; while (prs) { if (prs->peers_fe) err |= !resume_proxy(prs->peers_fe); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/haproxy-1.7.8/src/standard.c new/haproxy-1.7.9/src/standard.c --- old/haproxy-1.7.8/src/standard.c 2017-07-07 11:49:34.000000000 +0200 +++ new/haproxy-1.7.9/src/standard.c 2017-08-18 08:33:20.000000000 +0200 @@ -2841,6 +2841,60 @@ return dst; } +/* Returns the number of seconds since 01/01/1970 0:0:0 GMT for GMT date <tm>. + * It is meant as a portable replacement for timegm() for use with valid inputs. + * Returns undefined results for invalid dates (eg: months out of range 0..11). + */ +time_t my_timegm(const struct tm *tm) +{ + /* Each month has 28, 29, 30 or 31 days, or 28+N. The date in the year + * is thus (current month - 1)*28 + cumulated_N[month] to count the + * sum of the extra N days for elapsed months. The sum of all these N + * days doesn't exceed 30 for a complete year (366-12*28) so it fits + * in a 5-bit word. This means that with 60 bits we can represent a + * matrix of all these values at once, which is fast and efficient to + * access. The extra February day for leap years is not counted here. + * + * Jan : none = 0 (0) + * Feb : Jan = 3 (3) + * Mar : Jan..Feb = 3 (3 + 0) + * Apr : Jan..Mar = 6 (3 + 0 + 3) + * May : Jan..Apr = 8 (3 + 0 + 3 + 2) + * Jun : Jan..May = 11 (3 + 0 + 3 + 2 + 3) + * Jul : Jan..Jun = 13 (3 + 0 + 3 + 2 + 3 + 2) + * Aug : Jan..Jul = 16 (3 + 0 + 3 + 2 + 3 + 2 + 3) + * Sep : Jan..Aug = 19 (3 + 0 + 3 + 2 + 3 + 2 + 3 + 3) + * Oct : Jan..Sep = 21 (3 + 0 + 3 + 2 + 3 + 2 + 3 + 3 + 2) + * Nov : Jan..Oct = 24 (3 + 0 + 3 + 2 + 3 + 2 + 3 + 3 + 2 + 3) + * Dec : Jan..Nov = 26 (3 + 0 + 3 + 2 + 3 + 2 + 3 + 3 + 2 + 3 + 2) + */ + uint64_t extra = + ( 0ULL << 0*5) + ( 3ULL << 1*5) + ( 3ULL << 2*5) + /* Jan, Feb, Mar, */ + ( 6ULL << 3*5) + ( 8ULL << 4*5) + (11ULL << 5*5) + /* Apr, May, Jun, */ + (13ULL << 6*5) + (16ULL << 7*5) + (19ULL << 8*5) + /* Jul, Aug, Sep, */ + (21ULL << 9*5) + (24ULL << 10*5) + (26ULL << 11*5); /* Oct, Nov, Dec, */ + + unsigned int y = tm->tm_year + 1900; + unsigned int m = tm->tm_mon; + unsigned long days = 0; + + /* days since 1/1/1970 for full years */ + days += days_since_zero(y) - days_since_zero(1970); + + /* days for full months in the current year */ + days += 28 * m + ((extra >> (m * 5)) & 0x1f); + + /* count + 1 after March for leap years. A leap year is a year multiple + * of 4, unless it's multiple of 100 without being multiple of 400. 2000 + * is leap, 1900 isn't, 1904 is. + */ + if ((m > 1) && !(y & 3) && ((y % 100) || !(y % 400))) + days++; + + days += tm->tm_mday - 1; + return days * 86400ULL + tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec; +} + /* This function check a char. It returns true and updates * <date> and <len> pointer to the new position if the * character is found.
