From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.cs.ucla.edu (mail.cs.ucla.edu [131.179.128.66]) by sourceware.org (Postfix) with ESMTPS id 113803858D1E for ; Sat, 8 Apr 2023 22:08:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 113803858D1E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=cs.ucla.edu Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=cs.ucla.edu Received: from localhost (localhost [127.0.0.1]) by mail.cs.ucla.edu (Postfix) with ESMTP id 7E8333C09FA05; Sat, 8 Apr 2023 15:08:36 -0700 (PDT) Received: from mail.cs.ucla.edu ([127.0.0.1]) by localhost (mail.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id vaRlPZ-IeY23; Sat, 8 Apr 2023 15:08:35 -0700 (PDT) Received: from localhost (localhost [127.0.0.1]) by mail.cs.ucla.edu (Postfix) with ESMTP id 4EF0A3C09FA06; Sat, 8 Apr 2023 15:08:35 -0700 (PDT) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.cs.ucla.edu 4EF0A3C09FA06 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cs.ucla.edu; s=9D0B346E-2AEB-11ED-9476-E14B719DCE6C; t=1680991715; bh=x238u0yXpgyfY5eP326+r1bLOQgV5/Jde2pFPBCd8uA=; h=Message-ID:Date:MIME-Version:To:From; b=glAx7nZ4KlF1uldnwJbSQ415XOni8mMrC8OcbquYfov2RoH1at2LvQDgGYu7GNtpD mq9YtqcVskq9hyoOVHtTu7XNxwfP2m8dMbd2Ma1/BInUA78UZDFG/qTSosc0UpRq5G Wkvt21KnCccCY5xeA7xLcaD3OOAL/3XzoB+TcwgHzDLRW1RywqJIBYu3j/99m6MKAN ujZd298oeV7RoGpvlRSVrwuv0qIWbSezF+NJYct0exoMCS3iTCCfD1RsSm49+Db5mY hJ6R87o0/tzzFuciCEIsPO45755l2gs8dxFZ64zL8XPmiqloM5MmTW4WFhNg1AfEDc QiES4NamosgHw== X-Virus-Scanned: amavisd-new at mail.cs.ucla.edu Received: from mail.cs.ucla.edu ([127.0.0.1]) by localhost (mail.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id zRyKurPYWcxU; Sat, 8 Apr 2023 15:08:35 -0700 (PDT) Received: from [192.168.1.9] (cpe-172-91-119-151.socal.res.rr.com [172.91.119.151]) by mail.cs.ucla.edu (Postfix) with ESMTPSA id 243913C09FA05; Sat, 8 Apr 2023 15:08:35 -0700 (PDT) Content-Type: multipart/mixed; boundary="------------YSQr7qhAa4TxiScTpks4PtPO" Message-ID: <3e699937-2b0d-7218-3f97-ab54154806c1@cs.ucla.edu> Date: Sat, 8 Apr 2023 15:08:34 -0700 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.9.0 Content-Language: en-US To: Florian Weimer References: Cc: libc-alpha@sourceware.org From: Paul Eggert Organization: UCLA Computer Science Department Subject: Re: [PATCH 1/2] Implement strlcpy and strlcat [BZ #178] In-Reply-To: X-Spam-Status: No, score=-8.2 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,GIT_PATCH_0,JMQ_SPF_NEUTRAL,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: This is a multi-part message in MIME format. --------------YSQr7qhAa4TxiScTpks4PtPO Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable On 2023-04-05 04:20, Florian Weimer via Libc-alpha wrote: > The fortified strlcat implementation does not raise SIGABRT if the > destination buffer does not contain a null terminator, it just > inheritis the non-failing regular strlcat behavior. Maybe this > should be changed to catch secondary overflows because the string > appears longer than the buffer. Shouldn't it should work like fortified strcat, which raises SIGABRT if=20 the destination is not null-terminated? (Admittedly this isn't important.= ) > +* The strlcpy and strlcat functions have been added. They are derived > + from OpenBSD, and are expected to be added to a future POSIX version= s. versions =E2=86=92 version Please see the attached patch for a fix for this. > +* The functions strlcpy and strlcat have been added. That's a duplicate in NEWS. > +extern __typeof (strlcpy) __strlcpy; > +libc_hidden_proto (__strlcpy) > +extern __typeof (strlcat) __strlcat; > +libc_hidden_proto (__strlcat) Glibc shouldn't call these functions internally, so let's not export=20 them to elsewhere in glibc. manual/maint.texi needs changing too (see where it discusses strncpy). > --- a/manual/string.texi > +++ b/manual/string.texi When the manual discusses strcat/strncat's O(N**2) drawback it should do=20 the same for strlcat. > +This function is similar to @code{strcpy}, but copies at most > +@var{size} bytes from the string @var{from} into the destination > +array @var{to}, including a terminating null byte. This should mention draft POSIX's recommendation that the caller should=20 ensure that SIZE has room for the terminating null. Also, it shouldn't=20 say it copies at most SIZE bytes because it's really at most (MAX (1,=20 SIZE) - 1). There are several errors of this sort later on - for=20 example, the overlapping move constraint doesn't apply to the null=20 terminator. I think I caught the errors in the attached patch but=20 another pair of eyes wouldn't hurt. Also, let's use similar wording for strlcpy and strlcat to avoid having=20 the readers think that there are differences when there aren't any. > +The return value @var{result} of @code{strlcpy} is the length of the > +string @var{from}. This means that @samp{@var{result} >=3D @var{size}= } is > +true whenever truncation occurs. It's not just "whenever" (i.e., if); it's if and only if. > +The behavior of @code{strlcpy} is undefined if @var{size} is zero, or = if > +the source string and the first @var{size} bytes of the destination > +array overlap. Actually, the behavior is well-defined if SIZE is zero. It's also=20 well-defined in some cases when the first SIZE bytes overlap: the only=20 constraint is that the region copied from cannot overlap with the region=20 copied to (in both cases, not counting any terminating null). However,=20 behavior is undefined if either pointer is null, or if the destination=20 array isn't big enough. The description should allude to the truncation-warning discussion below. There are similar issues for the strlcat doc, which the attached patch=20 also attempts to fix. > + /* If the sum wraps around, we have more than SIZE_MAX + 2 bytes in > + the two input strings (including both null terminators). If each > + byte in the address space can be assigned a unique size_t value > + (which the static_assert checks), then by the pigeonhole > + principle, the two input strings must overlap, which is > + undefined. */ > + _Static_assert (sizeof (uintptr_t) =3D=3D sizeof (size_t), > + "theoretical maximum object size covers address space"); Change the "=3D=3D" to "<=3D" (since that's what is meant here) and clari= fy=20 the comment which is a bit confusing. Better yet, let's omit this and=20 all related code and go with the OpenBSD implementation. > + /* Copy the leading portion of the string. The last > + character is subsequently overwritten with the NUL > + terminator, but the destination size is usually a > + multiple of a small power of two, so writing it twice > + should be more efficient than copying an odd number of > + bytes. */ > + memcpy (dest, src, size); > + dest[size - 1] =3D '\0'; This micro-optimization is incorrect, as it's valid for dest to equal=20 src + size - 1, and that means the memcpy overlaps which is undefined.=20 Change it to memcpy (dest, src, size - 1) and lose the comment. Or=20 change it to memmove and lengthen the comment. Or better yet, get rid of=20 all code like this (there are other instances), and use the simple=20 OpenBSD implementation which will more likely match what callers expect=20 (in the rare cases where the behaviors differ) and will possibly be=20 faster despite not using memcpy. Proposed patch for NEWS and manual attached; the other problems remain=20 unfixed. --------------YSQr7qhAa4TxiScTpks4PtPO Content-Type: text/x-patch; charset=UTF-8; name="0001-manual-improve-strlcpy-strlcat-doc.patch" Content-Disposition: attachment; filename="0001-manual-improve-strlcpy-strlcat-doc.patch" Content-Transfer-Encoding: base64 RnJvbSBlZGQ1ODA4MWRmZmNiZDgzZjhmODlhN2FjYjlmMzIzNjUzYmQ3YTU2IE1vbiBTZXAg MTcgMDA6MDA6MDAgMjAwMQpGcm9tOiBQYXVsIEVnZ2VydCA8ZWdnZXJ0QGNzLnVjbGEuZWR1 PgpEYXRlOiBTYXQsIDggQXByIDIwMjMgMTM6NTQ6MzcgLTA3MDAKU3ViamVjdDogW1BBVENI XSBtYW51YWw6IGltcHJvdmUgc3RybGNweS9zdHJsY2F0IGRvYwoKKiBORVdTOiBSZW1vdmUg ZHVwbGljYXRlIGFubm91bmNlbWVudCBvZiBzdHJsY3B5L3N0cmxjYXQuCiogbWFudWFsL21h aW50LnRleGkgKFNvdXJjZSBGb3J0aWZpY2F0aW9uKToKTWVudGlvbiBzdHJsY3B5IGFuZCBz dHJsY2F0LgoqIG1hbnVhbC9zdHJpbmcudGV4aSAoVHJ1bmNhdGluZyBTdHJpbmdzKTogSW4g c3RybGNweS9zdHJsY2F0LAptZW50aW9uIHRoYXQgdGhlIGNhbGxlciBzaG91bGQgZW5zdXJl IHJvb20gZm9yIHRoZSB0ZXJtaW5hdGluZwpudWxsIGJ5dGUsIGFzIGRyYWZ0IFBPU0lYIGRv ZXMuICBEb24ndCBzYXkgdGhhdCB0aGUgYmVoYXZpb3IKaXMgdW5kZWZpbmVkIG1lcmVseSBi ZWNhdXNlIHRoZSBzaXplIGlzIHplcm8sIHNpbmNlIGl0J3Mgd2VsbCBkZWZpbmVkLgpBY2N1 cmF0ZWx5IGRlc2NyaWJlIHRoZSBwcm9oaWJpdGlvbiBhZ2FpbnN0IG92ZXJsYXBwaW5nIGNv cGllcy4KVXNlIHRoZSBzYW1lIGxhbmd1YWdlIGFib3V0IHN0cmluZy1wcm9jZXNzaW5nIGNo b2ljZQphbmQgYWJvdXQgcGVyZm9ybWFuY2UgdGhhdCB3ZSBhbHJlYWR5IHVzZSBmb3Igc3Ry bmNweSBhbmQgc3RybmNhdC4KQXZvaWQgdW5uZWNlc3NhcmlseS1kaWZmZXJlbnQgd29yZGlu ZyBiZXR3ZWVuIHN0cmxjcHkgYW5kIHN0cmxjYXQKdGhhdCBtaWdodCBjYXVzZSB0aGUgcmVh ZGVyIHRvIG1pc3Rha2VubHkgdGhpbmsgb2Ygb3RoZXIgZGlmZmVyZW5jZXMuCk1lbnRpb24g dGhhdCBzdHJsY3B5IGlzIE8obWF4KHNpemUsIHN0cmxlbihzcmMpKSksIG5vdCBPKHNpemUp LgotLS0KIE5FV1MgICAgICAgICAgICAgICB8ICA0ICstLQogbWFudWFsL21haW50LnRleGkg IHwgIDQgKysrCiBtYW51YWwvc3RyaW5nLnRleGkgfCA2NSArKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrLS0tLS0tLS0tLS0tLS0tCiAzIGZpbGVzIGNoYW5nZWQsIDQ5IGluc2Vy dGlvbnMoKyksIDI0IGRlbGV0aW9ucygtKQoKZGlmZiAtLWdpdCBhL05FV1MgYi9ORVdTCmlu ZGV4IDYwYjQwZmFiY2YuLmIyMWM0YzEwYWEgMTAwNjQ0Ci0tLSBhL05FV1MKKysrIGIvTkVX UwpAQCAtMjIsNyArMjIsNyBAQCBNYWpvciBuZXcgZmVhdHVyZXM6CiAqIFBSSWIqIGFuZCBQ UklCKiBtYWNyb3MgZnJvbSBDMlggaGF2ZSBiZWVuIGFkZGVkIHRvIDxpbnR0eXBlcy5oPi4K IAogKiBUaGUgc3RybGNweSBhbmQgc3RybGNhdCBmdW5jdGlvbnMgaGF2ZSBiZWVuIGFkZGVk LiAgVGhleSBhcmUgZGVyaXZlZAotICBmcm9tIE9wZW5CU0QsIGFuZCBhcmUgZXhwZWN0ZWQg dG8gYmUgYWRkZWQgdG8gYSBmdXR1cmUgUE9TSVggdmVyc2lvbnMuCisgIGZyb20gT3BlbkJT RCwgYW5kIGFyZSBleHBlY3RlZCB0byBiZSBhZGRlZCB0byBhIGZ1dHVyZSBQT1NJWCB2ZXJz aW9uLgogCiBEZXByZWNhdGVkIGFuZCByZW1vdmVkIGZlYXR1cmVzLCBhbmQgb3RoZXIgY2hh bmdlcyBhZmZlY3RpbmcgY29tcGF0aWJpbGl0eToKIApAQCAtMjI2LDggKzIyNiw2IEBAIE1h am9yIG5ldyBmZWF0dXJlczoKIAogICBUaGUgTG9vbmdBcmNoIEFCSSBpcyA2NC1iaXQgbGl0 dGxlLWVuZGlhbi4KIAotKiBUaGUgZnVuY3Rpb25zIHN0cmxjcHkgYW5kIHN0cmxjYXQgaGF2 ZSBiZWVuIGFkZGVkLgotCiBEZXByZWNhdGVkIGFuZCByZW1vdmVkIGZlYXR1cmVzLCBhbmQg b3RoZXIgY2hhbmdlcyBhZmZlY3RpbmcgY29tcGF0aWJpbGl0eToKIAogKiBTdXBwb3J0IGZv ciBwcmVsaW5rIHdpbGwgYmUgcmVtb3ZlZCBpbiB0aGUgbmV4dCByZWxlYXNlOyB0aGlzIGlu Y2x1ZGVzCmRpZmYgLS1naXQgYS9tYW51YWwvbWFpbnQudGV4aSBiL21hbnVhbC9tYWludC50 ZXhpCmluZGV4IGE4NDQxZTIwYjYuLjNhZDQ2NDdjZjMgMTAwNjQ0Ci0tLSBhL21hbnVhbC9t YWludC50ZXhpCisrKyBiL21hbnVhbC9tYWludC50ZXhpCkBAIC0zNzEsNiArMzcxLDEwIEBA IFRoZSBmb2xsb3dpbmcgZnVuY3Rpb25zIGFuZCBtYWNyb3MgYXJlIGZvcnRpZmllZCBpbiBA dGhlZ2xpYmN7fToKIAogQGl0ZW0gQGNvZGV7c3RyY3B5fQogCitAaXRlbSBAY29kZXtzdHJs Y2F0fQorCitAaXRlbSBAY29kZXtzdHJsY3B5fQorCiBAaXRlbSBAY29kZXtzdHJuY2F0fQog CiBAaXRlbSBAY29kZXtzdHJuY3B5fQpkaWZmIC0tZ2l0IGEvbWFudWFsL3N0cmluZy50ZXhp IGIvbWFudWFsL3N0cmluZy50ZXhpCmluZGV4IDU3ZTNmNmE2MTkuLjc4Y2RjMDEyZDAgMTAw NjQ0Ci0tLSBhL21hbnVhbC9zdHJpbmcudGV4aQorKysgYi9tYW51YWwvc3RyaW5nLnRleGkK QEAgLTcyNiw4ICs3MjYsOCBAQCBUaGlzIGZ1bmN0aW9uIGhhcyB1bmRlZmluZWQgcmVzdWx0 cyBpZiB0aGUgc3RyaW5ncyBvdmVybGFwLgogQXMgbm90ZWQgYmVsb3csIHRoaXMgZnVuY3Rp b24gaGFzIHNpZ25pZmljYW50IHBlcmZvcm1hbmNlIGlzc3Vlcy4KIEBlbmQgZGVmdHlwZWZ1 bgogCi1Qcm9ncmFtbWVycyB1c2luZyB0aGUgQGNvZGV7c3RyY2F0fSBvciBAY29kZXt3Y3Nj YXR9IGZ1bmN0aW9uIChvciB0aGUKLUBjb2Rle3N0cm5jYXR9IG9yIEBjb2Rle3djc25jYXR9 IGZ1bmN0aW9ucyBkZWZpbmVkIGluCitQcm9ncmFtbWVycyB1c2luZyB0aGUgQGNvZGV7c3Ry Y2F0fSBvciBAY29kZXt3Y3NjYXR9IGZ1bmN0aW9ucyAob3IgdGhlCitAY29kZXtzdHJsY2F0 fSwgQGNvZGV7c3RybmNhdH0gYW5kIEBjb2Rle3djc25jYXR9IGZ1bmN0aW9ucyBkZWZpbmVk IGluCiBhIGxhdGVyIHNlY3Rpb24sIGZvciB0aGF0IG1hdHRlcikKIGNhbiBlYXNpbHkgYmUg cmVjb2duaXplZCBhcyBsYXp5IGFuZCByZWNrbGVzcy4gIEluIGFsbW9zdCBhbGwgc2l0dWF0 aW9ucwogdGhlIGxlbmd0aHMgb2YgdGhlIHBhcnRpY2lwYXRpbmcgc3RyaW5ncyBhcmUga25v d24gKGl0IGJldHRlciBzaG91bGQgYmUKQEAgLTg0OCw3ICs4NDgsOCBAQCBmdW5jdGlvbi4g IFRoZSBleGFtcGxlIHdvdWxkIHdvcmsgZm9yIHdpZGUgY2hhcmFjdGVycyB0aGUgc2FtZSB3 YXkuCiBXaGVuZXZlciBhIHByb2dyYW1tZXIgZmVlbHMgdGhlIG5lZWQgdG8gdXNlIEBjb2Rl e3N0cmNhdH0gc2hlIG9yIGhlCiBzaG91bGQgdGhpbmsgdHdpY2UgYW5kIGxvb2sgdGhyb3Vn aCB0aGUgcHJvZ3JhbSB0byBzZWUgd2hldGhlciB0aGUgY29kZSBjYW5ub3QKIGJlIHJld3Jp dHRlbiB0byB0YWtlIGFkdmFudGFnZSBvZiBhbHJlYWR5IGNhbGN1bGF0ZWQgcmVzdWx0cy4K LVRoZSByZWxhdGVkIGZ1bmN0aW9ucyBAY29kZXtzdHJuY2F0fSBhbmQgQGNvZGV7d2NzY2F0 fQorVGhlIHJlbGF0ZWQgZnVuY3Rpb25zIEBjb2Rle3N0cmxjYXR9LCBAY29kZXtzdHJuY2F0 fSwKK0Bjb2Rle3djc2NhdH0gYW5kIEBjb2Rle3djc25jYXR9CiBhcmUgYWxtb3N0IGFsd2F5 cyB1bm5lY2Vzc2FyeSwgdG9vLgogQWdhaW46IGl0IGlzIGFsbW9zdCBhbHdheXMgdW5uZWNl c3NhcnkgdG8gdXNlIGZ1bmN0aW9ucyBsaWtlIEBjb2Rle3N0cmNhdH0uCiAKQEAgLTEwNzks MTMgKzEwODAsMTUgQEAgaXNzdWVzLiAgQHhyZWZ7Q29uY2F0ZW5hdGluZyBTdHJpbmdzfS4K IEBkZWZ0eXBlZnVuIHNpemVfdCBzdHJsY3B5IChjaGFyICpyZXN0cmljdCBAdmFye3RvfSwg Y29uc3QgY2hhciAqcmVzdHJpY3QgQHZhcntmcm9tfSwgc2l6ZV90IEB2YXJ7c2l6ZX0pCiBA c3RhbmRhcmRze0JTRCwgc3RyaW5nLmh9CiBAc2FmZXR5e0BwcmVsaW17fUBtdHNhZmV7fUBh c3NhZmV7fUBhY3NhZmV7fX0KLVRoaXMgZnVuY3Rpb24gaXMgc2ltaWxhciB0byBAY29kZXtz dHJjcHl9LCBidXQgY29waWVzIGF0IG1vc3QKLUB2YXJ7c2l6ZX0gYnl0ZXMgZnJvbSB0aGUg c3RyaW5nIEB2YXJ7ZnJvbX0gaW50byB0aGUgZGVzdGluYXRpb24KLWFycmF5IEB2YXJ7dG99 LCBpbmNsdWRpbmcgYSB0ZXJtaW5hdGluZyBudWxsIGJ5dGUuCitUaGlzIGZ1bmN0aW9uIGNv cGllcyB0aGUgc3RyaW5nIEB2YXJ7ZnJvbX0gdG8gdGhlIGRlc3RpbmF0aW9uIGFycmF5CitA dmFye3RvfSwgbGltaXRpbmcgdGhlIHJlc3VsdCdzIHNpemUgKGluY2x1ZGluZyB0aGUgbnVs bCB0ZXJtaW5hdG9yKQordG8gQHZhcntzaXplfS4gIFRoZSBjYWxsZXIgc2hvdWxkIGVuc3Vy ZSB0aGF0IEB2YXJ7c2l6ZX0gaW5jbHVkZXMgcm9vbQorZm9yIHRoZSByZXN1bHQncyB0ZXJt aW5hdGluZyBudWxsIGJ5dGUuCiAKIElmIEB2YXJ7c2l6ZX0gaXMgZ3JlYXRlciB0aGFuIHRo ZSBsZW5ndGggb2YgdGhlIHN0cmluZyBAdmFye2Zyb219LAotdGhpcyBmdW5jdGlvbiBjb3Bp ZXMgYWxsIG9mIHRoZSBzdHJpbmcgQHZhcntmcm9tfSB0byB0aGUgZGVzdGluYXRpb24KLWFy cmF5IEB2YXJ7dG99LCBpbmNsdWRpbmcgdGhlIHRlcm1pbmF0aW5nIG51bGwgYnl0ZS4gIExp a2Ugb3RoZXIKK3RoaXMgZnVuY3Rpb24gY29waWVzIHRoZSBub24tbnVsbCBieXRlcyBvZiB0 aGUgc3RyaW5nCitAdmFye2Zyb219IHRvIHRoZSBkZXN0aW5hdGlvbiBhcnJheSBAdmFye3Rv fSwKK2FuZCB0ZXJtaW5hdGVzIHRoZSBjb3B5IHdpdGggYSBudWxsIGJ5dGUuICBMaWtlIG90 aGVyCiBzdHJpbmcgZnVuY3Rpb25zIHN1Y2ggYXMgQGNvZGV7c3RyY3B5fSwgYnV0IHVubGlr ZSBAY29kZXtzdHJuY3B5fSwgYW55CiByZW1haW5pbmcgYnl0ZXMgaW4gdGhlIGRlc3RpbmF0 aW9uIGFycmF5IHJlbWFpbiB1bmNoYW5nZWQuCiAKQEAgLTEwOTQsMTMgKzEwOTcsMjIgQEAg SWYgQHZhcntzaXplfSBpcyBub256ZXJvIGFuZCBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhl IHRoZSBsZW5ndGggb2YgdGhlIHN0cmluZwogYnl0ZXMgdG8gdGhlIGRlc3RpbmF0aW9uIGFy cmF5IEB2YXJ7dG99LCBhbmQgd3JpdGVzIGEgdGVybWluYXRpbmcgbnVsbAogYnl0ZSB0byB0 aGUgbGFzdCBieXRlIG9mIHRoZSBhcnJheS4KIAotVGhlIHJldHVybiB2YWx1ZSBAdmFye3Jl c3VsdH0gb2YgQGNvZGV7c3RybGNweX0gaXMgdGhlIGxlbmd0aCBvZiB0aGUKLXN0cmluZyBA dmFye2Zyb219LiAgVGhpcyBtZWFucyB0aGF0IEBzYW1we0B2YXJ7cmVzdWx0fSA+PSBAdmFy e3NpemV9fSBpcwotdHJ1ZSB3aGVuZXZlciB0cnVuY2F0aW9uIG9jY3Vycy4KK1RoaXMgZnVu Y3Rpb24gcmV0dXJucyB0aGUgbGVuZ3RoIG9mIHRoZSBzdHJpbmcgQHZhcntmcm9tfS4gIFRo aXMgbWVhbnMKK3RoYXQgdHJ1bmNhdGlvbiBvY2N1cnMgaWYgYW5kIG9ubHkgaWYgdGhlIHJl dHVybmVkIHZhbHVlIGlzIGdyZWF0ZXIKK3RoYW4gb3IgZXF1YWwgdG8gQHZhcntzaXplfS4K IAotVGhlIGJlaGF2aW9yIG9mIEBjb2Rle3N0cmxjcHl9IGlzIHVuZGVmaW5lZCBpZiBAdmFy e3NpemV9IGlzIHplcm8sIG9yIGlmCi10aGUgc291cmNlIHN0cmluZyBhbmQgdGhlIGZpcnN0 IEB2YXJ7c2l6ZX0gYnl0ZXMgb2YgdGhlIGRlc3RpbmF0aW9uCi1hcnJheSBvdmVybGFwLgor VGhlIGJlaGF2aW9yIGlzIHVuZGVmaW5lZCBpZiBAdmFye3RvfSBvciBAdmFye2Zyb219IGlz IGEgbnVsbCBwb2ludGVyLAorb3IgaWYgdGhlIGRlc3RpbmF0aW9uIGFycmF5J3Mgc2l6ZSBp cyBib3RoIGxlc3MgdGhhbiBAdmFye3NpemV9IGFuZAorbGVzcyB0aGFuIG9yIGVxdWFsIHRv IHRoZSBsZW5ndGggb2YgdGhlIHN0cmluZyBAdmFye2Zyb219LCBvciBpZgorY29weWluZyB0 YWtlcyBwbGFjZSBiZXR3ZWVuIGFycmF5cyB0aGF0IG92ZXJsYXAgKHRoYXQgaXMsIGlmCitA dmFye3NpemV9IGlzIG5vbi16ZXJvIGFuZCB0aGUgZmlyc3QgQHNhbXB7TUlOIChzdHJsZW4g KEB2YXJ7ZnJvbX0pLAorQHZhcntzaXplfSAtIDEpfSBieXRlcyBvZiBAdmFye2Zyb219IG92 ZXJsYXAgd2l0aCB0aGUgc2FtZSBudW1iZXIgb2YKK2J5dGVzIG9mIHRoZSB0aGUgZGVzdGlu YXRpb24gYXJyYXkpLgorCitBcyBub3RlZCBiZWxvdywgdGhpcyBmdW5jdGlvbiBpcyBnZW5l cmFsbHkgYSBwb29yIGNob2ljZSBmb3IKK3Byb2Nlc3Npbmcgc3RyaW5ncy4gIEFsc28sIHRo aXMgZnVuY3Rpb24gaGFzIGEgcGVyZm9ybWFuY2UgaXNzdWUsCithcyBpdHMgdGltZSBjb3N0 IGlzIHByb3BvcnRpb25hbCB0byB0aGUgbGVuZ3RoIG9mIEB2YXJ7ZnJvbX0KK2V2ZW4gd2hl biBAdmFye3NpemV9IGlzIHNtYWxsLgogCiBUaGlzIGZ1bmN0aW9uIGlzIGRlcml2ZWQgZnJv bSBPcGVuQlNEIDIuNC4KIEBlbmQgZGVmdHlwZWZ1bgpAQCAtMTEwOSw4ICsxMTIxLDkgQEAg VGhpcyBmdW5jdGlvbiBpcyBkZXJpdmVkIGZyb20gT3BlbkJTRCAyLjQuCiBAc3RhbmRhcmRz e0JTRCwgc3RyaW5nLmh9CiBAc2FmZXR5e0BwcmVsaW17fUBtdHNhZmV7fUBhc3NhZmV7fUBh Y3NhZmV7fX0KIFRoaXMgZnVuY3Rpb24gYXBwZW5kcyB0aGUgc3RyaW5nIEB2YXJ7ZnJvbX0g dG8gdGhlCi1zdHJpbmcgQHZhcnt0b30sIGxpbWl0aW5nIHRoZSB0b3RhbCBzaXplIG9mIHRo ZSByZXN1bHQgc3RyaW5nIGF0Ci1AdmFye3RvfSAoaW5jbHVkaW5nIHRoZSBudWxsIHRlcm1p bmF0b3IpIHRvIEB2YXJ7c2l6ZX0uCitzdHJpbmcgQHZhcnt0b30sIGxpbWl0aW5nIHRoZSBy ZXN1bHQncyB0b3RhbCBzaXplIChpbmNsdWRpbmcgdGhlIG51bGwKK3Rlcm1pbmF0b3IpIHRv IEB2YXJ7c2l6ZX0uICBUaGUgY2FsbGVyIHNob3VsZCBlbnN1cmUgdGhhdCBAdmFye3NpemV9 CitpbmNsdWRlcyByb29tIGZvciB0aGUgcmVzdWx0J3MgdGVybWluYXRpbmcgbnVsbCBieXRl LgogCiBUaGlzIGZ1bmN0aW9uIGNvcGllcyBhcyBtdWNoIGFzIHBvc3NpYmxlIG9mIHRoZSBz dHJpbmcgQHZhcntmcm9tfSBpbnRvCiB0aGUgYXJyYXkgYXQgQHZhcnt0b30gb2YgQHZhcntz aXplfSBieXRlcywgc3RhcnRpbmcgYXQgdGhlIHRlcm1pbmF0aW5nCkBAIC0xMTIwLDEyICsx MTMzLDIyIEBAIHN0cmluZyB3aWxsIGNvbnRhaW4gYSBudWxsIHRlcm1pbmF0b3IsIGl0IGNh biBiZSB0cnVuY2F0ZWQgKG5vdCBhbGwKIGJ5dGVzIGluIEB2YXJ7ZnJvbX0gbWF5IGJlIGNv cGllZCkuCiAKIFRoaXMgZnVuY3Rpb24gcmV0dXJucyB0aGUgc3VtIG9mIHRoZSBvcmlnaW5h bCBsZW5ndGggb2YgQHZhcnt0b30gYW5kCi10aGUgbGVuZ3RoIG9mIEB2YXJ7ZnJvbX0uICBU aGlzIG1lYW5zIHRoYXQgdHJ1bmNhdGlvbiBvY2N1cnMgdW5sZXNzCi10aGUgcmV0dXJuZWQg dmFsdWUgaXMgbGVzcyB0aGFuIEB2YXJ7c2l6ZX0uCit0aGUgbGVuZ3RoIG9mIEB2YXJ7ZnJv bX0uICBUaGlzIG1lYW5zIHRoYXQgdHJ1bmNhdGlvbiBvY2N1cnMgaWYgYW5kCitvbmx5IGlm IHRoZSByZXR1cm5lZCB2YWx1ZSBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gQHZhcntz aXplfS4KKworVGhlIGJlaGF2aW9yIGlzIHVuZGVmaW5lZCBpZiBAdmFye3RvfSBvciBAdmFy e2Zyb219IGlzIGEgbnVsbCBwb2ludGVyLAorb3IgaWYgdGhlIGRlc3RpbmF0aW9uIGFycmF5 IGRvZXMgbm90IGNvbnRhaW4gYSBudWxsIGJ5dGUgaW4gaXRzIGZpcnN0CitAdmFye3NpemV9 IGJ5dGVzLCBvciBpZiB0aGUgZGVzdGluYXRpb24gYXJyYXkncyBzaXplIGlzIGJvdGggbGVz cyB0aGFuCitAdmFye3NpemV9IGFuZCBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhlIHN1bSBv ZiB0aGUgbGVuZ3RocyBvZiB0aGUKK3N0cmluZ3MgQHZhcnt0b30gYW5kIEB2YXJ7ZnJvbX0s IG9yIGlmIGNvcHlpbmcgdGFrZXMgcGxhY2UgYmV0d2VlbgorYXJyYXlzIHRoYXQgb3Zlcmxh cCAodGhhdCBpcywgaWYgQHZhcntzaXplfSBpcyBub24temVybyBhbmQgdGhlCitmaXJzdCBA c2FtcHtNSU4gKHN0cmxlbiAoQHZhcntmcm9tfSksIEB2YXJ7c2l6ZX0gLSAxIC0gc3RybGVu IChAdmFye3RvfSkpfQorYnl0ZXMgb2YgQHZhcntmcm9tfSBvdmVybGFwIHdpdGggdGhlIHNh bWUgbnVtYmVyIG9mIGJ5dGVzIHN0YXJ0aW5nCithdCBAc2FtcHtAdmFye3RvfSArIHN0cmxl biAoQHZhcnt0b30pfS4KIAotVGhlIGJlaGF2aW9yIGlzIHVuZGVmaW5lZCBpZiB0aGUgYXJy YXkgYXQgQHZhcnt0b30gZG9lcyBub3QgY29udGFpbiBhCi1udWxsIGJ5dGUgaW4gaXRzIGZp cnN0IEB2YXJ7c2l6ZX0gYnl0ZXMsIG9yIGlmIHRoZSBzb3VyY2Ugc3RyaW5nIGFuZCB0aGUK LWZpcnN0IEB2YXJ7c2l6ZX0gYnl0ZXMgb2YgQHZhcnt0b30gb3ZlcmxhcC4KK0FzIG5vdGVk IGJlbG93LCB0aGlzIGZ1bmN0aW9uIGlzIGdlbmVyYWxseSBhIHBvb3IgY2hvaWNlIGZvcgor cHJvY2Vzc2luZyBzdHJpbmdzLiAgQWxzbywgdGhpcyBmdW5jdGlvbiBoYXMgc2lnbmlmaWNh bnQgcGVyZm9ybWFuY2UKK2lzc3Vlcy4gIEB4cmVme0NvbmNhdGVuYXRpbmcgU3RyaW5nc30u CiAKIFRoaXMgZnVuY3Rpb24gaXMgZGVyaXZlZCBmcm9tIE9wZW5CU0QgMi40LgogQGVuZCBk ZWZ0eXBlZnVuCi0tIAoyLjM5LjIKCg== --------------YSQr7qhAa4TxiScTpks4PtPO--