Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vklDo-001nsy-0p for pgsql-hackers@arkaria.postgresql.org; Tue, 27 Jan 2026 15:43:17 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vklDn-00EPc8-1E for pgsql-hackers@arkaria.postgresql.org; Tue, 27 Jan 2026 15:43:15 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vklDm-00EPc0-1i for pgsql-hackers@lists.postgresql.org; Tue, 27 Jan 2026 15:43:15 +0000 Received: from forward500b.mail.yandex.net ([2a02:6b8:c02:900:1:45:d181:d500]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vklDg-002aNu-2H for pgsql-hackers@lists.postgresql.org; Tue, 27 Jan 2026 15:43:13 +0000 Received: from mail-nwsmtp-smtp-production-main-87.sas.yp-c.yandex.net (mail-nwsmtp-smtp-production-main-87.sas.yp-c.yandex.net [IPv6:2a02:6b8:c1c:405:0:640:8814:0]) by forward500b.mail.yandex.net (Yandex) with ESMTPS id 67AEAC128E; Tue, 27 Jan 2026 18:43:01 +0300 (MSK) Received: by mail-nwsmtp-smtp-production-main-87.sas.yp-c.yandex.net (smtp/Yandex) with ESMTPSA id 0hjDZs3GCSw0-Xg85T2IU; Tue, 27 Jan 2026 18:43:01 +0300 X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tantorlabs.com; s=mail; t=1769528581; bh=TF3gLX7KzBndpwvJ9tEyzHzyS+0dQUF0/eGZVRCLF4A=; h=In-Reply-To:References:To:Subject:Message-ID:Date:From; b=0dWP7XY18ikf5c48XrsFKycv50NuC7RArD3Zh5HcgmYKsaK3qOrkEcXt4ANA9x8wd 7Denb1TZbw+XMIX1ME2IB/RFe10KGn3uCKJcQdkekPxH0SpVHFYPROMpLb/px14GgA hU5pWIsLdvLUZzChYC4BS4XrAgXMLBsEyJUOqZNo= Authentication-Results: mail-nwsmtp-smtp-production-main-87.sas.yp-c.yandex.net; dkim=pass header.i=@tantorlabs.com Content-Type: multipart/mixed; boundary="------------0IdV92Ix49zcby3y6J1wKa31" Message-ID: Date: Tue, 27 Jan 2026 18:43:00 +0300 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Hash-based MCV matching for large IN-lists To: David Geier , PostgreSQL Hackers References: <7db341e0-fbc6-4ec5-922c-11fdafe7be12@tantorlabs.com> <988e3168-6096-488a-bb42-787e1e8c21a4@tantorlabs.com> <6c068ed3-0ab1-4743-862a-343134f2bfa4@gmail.com> Content-Language: en-US From: Ilia Evdokimov In-Reply-To: <6c068ed3-0ab1-4743-862a-343134f2bfa4@gmail.com> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is a multi-part message in MIME format. --------------0IdV92Ix49zcby3y6J1wKa31 Content-Type: multipart/alternative; boundary="------------Ko30GaDC4pCDsRN3UNPoyAs0" --------------Ko30GaDC4pCDsRN3UNPoyAs0 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Hi, On 19.01.2026 17:01, David Geier wrote: > Does that mean that we get a different estimation result, depending on > if the IN list is smaller or not? I think we should avoid that because > estimation quality might flip for the user unexpectedly. I think you're right. To address this, I changed the hash-table entry to track an additional 'count' filed, representing how many times a particular value appears on the hashed side. When inserting into the hash table, if the value is already present, I increment 'count', otherwise, I create a new entry with count = 1 >>> The code in master currently calls an operator-specific selectivity >>> estimation function. For equality this is typically eqsel() but the >>> function can be specified during CREATE OPERATOR. >>> >>> Can be safely special-case the behavior of eqsel() for all possible >>> operators for the ScalarArrayOpExpr case? >> >> Unfortunately there is no safe way to make this optimization generic for >> arbitrary restrict functions, because a custom RESTRICT function does >> not have to use MCVs at all. IMO, in practice the vast majority of >> ScalarArrayOpExpr uses with = or <> rely on the built-in equality >> operators whose selectivity is computed by eqsel()/neqsel(), so I >> limited this optimization to those cases. > How did you do that? I cannot find the code that checks for that. In scalararraysel(), before attempting the hash-based path, we determine whether the operator behaves like equality or inequality based on its selectivity function: if (oprsel == F_EQSEL || oprsel == F_EQJOINSEL)     isEquality = true; else if (oprsel == F_NEQSEL || oprsel == F_NEQJOINSEL)     isInequality = true; Then the hash-based MCV matching is only attempted under: if ((isEquality || isInequality) && !is_join_clause) So effectively this restricts the optimization to operators whose selectivity is computed by eqsel()/neqsel() on restriction clauses. Join clauses (which would use eqjoinsel/neqjoinsel) are excluded via !is_join_clause > For the MCVs, can't we reuse some code from the eqjoinsel() optimization > we did? The entry and context structs look similar enough to only need one. I considered reusing pieces from the eqjoinsel() , but in practice it turned out to be difficult to share code cleanly. Also, when looking at this file more broadly, we already have multiple places that reimplement similar pattern. > Making the code more compact would ease reviewing a lot. Agreed — I also think making the code more compact would significantly ease reviewing. I’ve found a way to unify the Const-array and ArrayExpr cases: in the ArrayExpr path, we can first construct the same arrays as in the Const-array case (elem_values, elem_nulls), and additionally build a boolean array elem_const[] indicating whether each element is a Const. Then the hash-based MCV matching function can: - Ignore NULL and non-Const elements when building and probing the hash table. - Count how many non-Const elements are present. - After MCV and non-MCV constant handling, account for non-Const elements separately using var_eq_non_const() and fold their probabilities into the same ANY/ALL accumulation logic. I've attached v3 patch with it. To validate the same estimation results, I temporarily kept both implementations (hash-based and nested-loop) and compared their resulting selectivity values. Whenever they differed, I logged it. I ran regression tests and some local workload testing with this check enabled, and did not observe any mismatches. I attached patch with this logging. -- Best regards, Ilia Evdokimov, Tantor Labs LLC, https://tantorlabs.com/ --------------Ko30GaDC4pCDsRN3UNPoyAs0 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit

Hi,

On 19.01.2026 17:01, David Geier wrote:
Does that mean that we get a different estimation result, depending on
if the IN list is smaller or not? I think we should avoid that because
estimation quality might flip for the user unexpectedly.

I think you're right.

To address this, I changed the hash-table entry to track an additional 'count' filed, representing how many times a particular value appears on the hashed side. When inserting into the hash table, if the value is already present, I increment 'count', otherwise, I create a new entry with count = 1



      
The code in master currently calls an operator-specific selectivity
estimation function. For equality this is typically eqsel() but the
function can be specified during CREATE OPERATOR.

Can be safely special-case the behavior of eqsel() for all possible
operators for the ScalarArrayOpExpr case?

Unfortunately there is no safe way to make this optimization generic for
arbitrary restrict functions, because a custom RESTRICT function does
not have to use MCVs at all. IMO, in practice the vast majority of
ScalarArrayOpExpr uses with = or <> rely on the built-in equality
operators whose selectivity is computed by eqsel()/neqsel(), so I
limited this optimization to those cases.
How did you do that? I cannot find the code that checks for that.

In scalararraysel(), before attempting the hash-based path, we determine whether the operator behaves like equality or inequality based on its selectivity function:

if (oprsel == F_EQSEL || oprsel == F_EQJOINSEL)
    isEquality = true;
else if (oprsel == F_NEQSEL || oprsel == F_NEQJOINSEL)
    isInequality = true;

Then the hash-based MCV matching is only attempted under:

if ((isEquality || isInequality) && !is_join_clause)

So effectively this restricts the optimization to operators whose selectivity is computed by eqsel()/neqsel() on restriction clauses. Join clauses (which would use eqjoinsel/neqjoinsel) are excluded via !is_join_clause


For the MCVs, can't we reuse some code from the eqjoinsel() optimization
we did? The entry and context structs look similar enough to only need one.

I considered reusing pieces from the eqjoinsel() , but in practice it turned out to be difficult to share code cleanly. Also, when looking at this file more broadly, we already have multiple places that reimplement similar pattern.


Making the code more compact would ease reviewing a lot.

Agreed — I also think making the code more compact would significantly ease reviewing. I’ve found a way to unify the Const-array and ArrayExpr cases: in the ArrayExpr path, we can first construct the same arrays as in the Const-array case (elem_values, elem_nulls), and additionally build a boolean array elem_const[] indicating whether each element is a Const. Then the hash-based MCV matching function can:

- Ignore NULL and non-Const elements when building and probing the hash table.
- Count how many non-Const elements are present.
- After MCV and non-MCV constant handling, account for non-Const elements separately using var_eq_non_const() and fold their probabilities into the same ANY/ALL accumulation logic.

I've attached v3 patch with it.

To validate the same estimation results, I temporarily kept both implementations (hash-based and nested-loop) and compared their resulting selectivity values. Whenever they differed, I logged it. I ran regression tests and some local workload testing with this check enabled, and did not observe any mismatches. I attached patch with this logging.

-- 
Best regards,
Ilia Evdokimov,
Tantor Labs LLC,
https://tantorlabs.com/


--------------Ko30GaDC4pCDsRN3UNPoyAs0-- --------------0IdV92Ix49zcby3y6J1wKa31 Content-Type: text/x-patch; charset=UTF-8; name="hash_mcv_in_logging.patch" Content-Disposition: attachment; filename="hash_mcv_in_logging.patch" Content-Transfer-Encoding: base64 ZGlmZiAtLWdpdCBhL3NyYy9iYWNrZW5kL3V0aWxzL2FkdC9zZWxmdW5jcy5jIGIvc3JjL2Jh Y2tlbmQvdXRpbHMvYWR0L3NlbGZ1bmNzLmMKaW5kZXggZjZkOTk3NzNiNzAuLmY0YzdmYjYw NWNlIDEwMDY0NAotLS0gYS9zcmMvYmFja2VuZC91dGlscy9hZHQvc2VsZnVuY3MuYworKysg Yi9zcmMvYmFja2VuZC91dGlscy9hZHQvc2VsZnVuY3MuYwpAQCAtMTk2Niw3ICsxOTY2LDcg QEAgc2NhbGFyYXJyYXlzZWwoUGxhbm5lckluZm8gKnJvb3QsCiAJVHlwZUNhY2hlRW50cnkg KnR5cGVudHJ5OwogCVJlZ1Byb2NlZHVyZSBvcHJzZWw7CiAJRm1nckluZm8Jb3Byc2VscHJv YzsKLQlTZWxlY3Rpdml0eSBzMTsKKwlTZWxlY3Rpdml0eSBzMSwgaGFzaF9zZWxlYyA9IC0x LjA7CiAJU2VsZWN0aXZpdHkgczFkaXNqb2ludDsKIAogCS8qIEZpcnN0LCBkZWNvbnN0cnVj dCB0aGUgZXhwcmVzc2lvbiAqLwpAQCAtMjEwNiw3ICsyMTA2LDcgQEAgc2NhbGFyYXJyYXlz ZWwoUGxhbm5lckluZm8gKnJvb3QsCiAJCQkJUmVsZWFzZVZhcmlhYmxlU3RhdHModmFyZGF0 YSk7CiAKIAkJCQlpZiAoczEgPj0gMC4wKQotCQkJCQlyZXR1cm4gczE7CisJCQkJCWhhc2hf c2VsZWMgPSBzMTsKIAkJCX0KIAkJfQogCkBAIC0yMTczLDYgKzIxNzMsOSBAQCBzY2FsYXJh cnJheXNlbChQbGFubmVySW5mbyAqcm9vdCwKIAkJaWYgKCh1c2VPciA/IGlzRXF1YWxpdHkg OiBpc0luZXF1YWxpdHkpICYmCiAJCQlzMWRpc2pvaW50ID49IDAuMCAmJiBzMWRpc2pvaW50 IDw9IDEuMCkKIAkJCXMxID0gczFkaXNqb2ludDsKKworCQlpZiAoaGFzaF9zZWxlYyA+PSAw ICYmIGZhYnMoczEgLSBoYXNoX3NlbGVjKSA+IDAuMDAwMDAwMDAwMDAxKQorCQkJZWxvZyhM T0csICJuZXN0ZWRfbG9vcCBzZWxlY3Rpdml0eSA9ICVmLCBoYXNoX2xvb3Agc2VsZWN0aXZp dHkgPSAlZiIsIHMxLCBoYXNoX3NlbGVjKTsKIAl9CiAJZWxzZSBpZiAocmlnaHRvcCAmJiBJ c0EocmlnaHRvcCwgQXJyYXlFeHByKSAmJgogCQkJICEoKEFycmF5RXhwciAqKSByaWdodG9w KS0+bXVsdGlkaW1zKQpAQCAtMjI1MSw3ICsyMjU0LDcgQEAgc2NhbGFyYXJyYXlzZWwoUGxh bm5lckluZm8gKnJvb3QsCiAJCQkJUmVsZWFzZVZhcmlhYmxlU3RhdHModmFyZGF0YSk7CiAK IAkJCQlpZiAoczEgPj0gMC4wKQotCQkJCQlyZXR1cm4gczE7CisJCQkJCWhhc2hfc2VsZWMg PSBzMTsKIAkJCX0KIAkJfQogCkBAIC0yMzEwLDYgKzIzMTMsOSBAQCBzY2FsYXJhcnJheXNl bChQbGFubmVySW5mbyAqcm9vdCwKIAkJaWYgKCh1c2VPciA/IGlzRXF1YWxpdHkgOiBpc0lu ZXF1YWxpdHkpICYmCiAJCQlzMWRpc2pvaW50ID49IDAuMCAmJiBzMWRpc2pvaW50IDw9IDEu MCkKIAkJCXMxID0gczFkaXNqb2ludDsKKworCQlpZiAoaGFzaF9zZWxlYyA+PSAwICYmIGZh YnMoczEgLSBoYXNoX3NlbGVjKSA+IDAuMDAwMDAwMDAwMDAxKQorCQkJZWxvZyhMT0csICJu ZXN0ZWRfbG9vcCBzZWxlY3Rpdml0eSA9ICVmLCBoYXNoX2xvb3Agc2VsZWN0aXZpdHkgPSAl ZiIsIHMxLCBoYXNoX3NlbGVjKTsKIAl9CiAJZWxzZQogCXsK --------------0IdV92Ix49zcby3y6J1wKa31 Content-Type: text/x-patch; charset=UTF-8; name="v3-0001-Use-hash-based-MCV-matching-for-ScalarArrayOpExpr.patch" Content-Disposition: attachment; filename*0="v3-0001-Use-hash-based-MCV-matching-for-ScalarArrayOpExpr.pa"; filename*1="tch" Content-Transfer-Encoding: base64 RnJvbSBkNDM5Njc0YjM3NTJkZDc4NjJiY2JiMTMyZGIyZGM5MTk5NmIxYTNjIE1vbiBTZXAg MTcgMDA6MDA6MDAgMjAwMQpGcm9tOiBJbGlhIEV2ZG9raW1vdiA8aWx5YS5ldmRva2ltb3ZA dGFudG9ybGFicy5ydT4KRGF0ZTogVHVlLCAyNyBKYW4gMjAyNiAxODoyNDo1MCArMDMwMApT dWJqZWN0OiBbUEFUQ0ggdjNdIFVzZSBoYXNoLWJhc2VkIE1DViBtYXRjaGluZyBmb3IgU2Nh bGFyQXJyYXlPcEV4cHIKIHNlbGVjdGl2aXR5CgpXaGVuIGVzdGltYXRpbmcgc2VsZWN0aXZp dHkgZm9yIFNjYWxhckFycmF5T3BFeHByIChJTiAvIEFOWSAvIEFMTCkgd2l0aAphdmFpbGFi bGUgTUNWIHN0YXRpc3RpY3MsIHRoZSBwbGFubmVyIGN1cnJlbnRseSBtYXRjaGVzIElOLWxp c3QgZWxlbWVudHMKYWdhaW5zdCB0aGUgTUNWIGFycmF5IHVzaW5nIG5lc3RlZCBsb29wcy4g Rm9yIGxhcmdlIElOLWxpc3RzIGFuZC9vciBsYXJnZQpNQ1YgbGlzdHMgdGhpcyBsZWFkcyB0 byBPKE4qTSkgcGxhbm5pbmctdGltZSBiZWhhdmlvci4KClRoaXMgcGF0Y2ggYWRkcyBhIGhh c2gtYmFzZWQgbWF0Y2hpbmcgc3RyYXRlZ3ksIHNpbWlsYXIgdG8gdGhlIG9uZSB1c2VkCmlu IGpvaW4gc2VsZWN0aXZpdHkgZXN0aW1hdGlvbi4gV2hlbiBNQ1Ygc3RhdGlzdGljcyBhcmUg YXZhaWxhYmxlIGFuZCB0aGUKb3BlcmF0b3Igc3VwcG9ydHMgaGFzaGluZywgdGhlIHNtYWxs ZXIgb2YgdGhlIHR3byBpbnB1dHMgKE1DViBsaXN0IG9yCklOLWxpc3QgY29uc3RhbnQgZWxl bWVudHMpIGlzIGNob3NlbiBhcyB0aGUgaGFzaCB0YWJsZSBidWlsZCBzaWRlLCBhbmQKdGhl IG90aGVyIHNpZGUgaXMgc2Nhbm5lZCBvbmNlLCByZWR1Y2luZyBjb21wbGV4aXR5IHRvIE8o TitNKS4KClRoZSBoYXNoLWJhc2VkIHBhdGggaXMgcmVzdHJpY3RlZCB0byBlcXVhbGl0eSBh bmQgaW5lcXVhbGl0eSBvcGVyYXRvcnMKdGhhdCB1c2UgZXFzZWwoKS9uZXFzZWwoKSwgYW5k IGlzIGFwcGxpZWQgb25seSB3aGVuIHN1aXRhYmxlIGhhc2gKZnVuY3Rpb25zIGFuZCBNQ1Yg c3RhdGlzdGljcyBhcmUgYXZhaWxhYmxlLgotLS0KIHNyYy9iYWNrZW5kL3V0aWxzL2FkdC9z ZWxmdW5jcy5jIHwgNTg4ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKy0KIHNyYy90 b29scy9wZ2luZGVudC90eXBlZGVmcy5saXN0IHwgICAzICsKIDIgZmlsZXMgY2hhbmdlZCwg NTkwIGluc2VydGlvbnMoKyksIDEgZGVsZXRpb24oLSkKCmRpZmYgLS1naXQgYS9zcmMvYmFj a2VuZC91dGlscy9hZHQvc2VsZnVuY3MuYyBiL3NyYy9iYWNrZW5kL3V0aWxzL2FkdC9zZWxm dW5jcy5jCmluZGV4IDI5ZmVjNjU1NTkzLi5mNmQ5OTc3M2I3MCAxMDA2NDQKLS0tIGEvc3Jj L2JhY2tlbmQvdXRpbHMvYWR0L3NlbGZ1bmNzLmMKKysrIGIvc3JjL2JhY2tlbmQvdXRpbHMv YWR0L3NlbGZ1bmNzLmMKQEAgLTE0Niw3ICsxNDYsNyBAQAogLyoKICAqIEluIHByb2R1Y3Rp b24gYnVpbGRzLCBzd2l0Y2ggdG8gaGFzaC1iYXNlZCBNQ1YgbWF0Y2hpbmcgd2hlbiB0aGUg bGlzdHMgYXJlCiAgKiBsYXJnZSBlbm91Z2ggdG8gYW1vcnRpemUgaGFzaCBzZXR1cCBjb3N0 LiAgKFRoaXMgdGhyZXNob2xkIGlzIGNvbXBhcmVkIHRvCi0gKiB0aGUgc3VtIG9mIHRoZSBs ZW5ndGhzIG9mIHRoZSB0d28gTUNWIGxpc3RzLiAgVGhpcyBpcyBzaW1wbGlzdGljIGJ1dCBz ZWVtcworICogdGhlIHN1bSBvZiB0aGUgbGVuZ3RocyBvZiB0aGUgdHdvIGxpc3RzLiAgVGhp cyBpcyBzaW1wbGlzdGljIGJ1dCBzZWVtcwogICogdG8gd29yayB3ZWxsIGVub3VnaC4pICBJ biBkZWJ1ZyBidWlsZHMsIHdlIHVzZSBhIHNtYWxsZXIgdGhyZXNob2xkIHNvIHRoYXQKICAq IHRoZSByZWdyZXNzaW9uIHRlc3RzIGNvdmVyIGJvdGggcGF0aHMgd2VsbC4KICAqLwpAQCAt MTU2LDYgKzE1NiwxMiBAQAogI2RlZmluZSBFUUpPSU5TRUxfTUNWX0hBU0hfVEhSRVNIT0xE IDIwCiAjZW5kaWYKIAorI2lmbmRlZiBVU0VfQVNTRVJUX0NIRUNLSU5HCisjZGVmaW5lIFND QUxBUkFSUkFZX01DVl9IQVNIX1RIUkVTSE9MRCAyMDAKKyNlbHNlCisjZGVmaW5lIFNDQUxB UkFSUkFZX01DVl9IQVNIX1RIUkVTSE9MRCAyMAorI2VuZGlmCisKIC8qIEVudHJpZXMgaW4g dGhlIHNpbXBsZWhhc2ggaGFzaCB0YWJsZSB1c2VkIGJ5IGVxam9pbnNlbF9maW5kX21hdGNo ZXMgKi8KIHR5cGVkZWYgc3RydWN0IE1DVkhhc2hFbnRyeQogewpAQCAtMTc2LDE0ICsxODIs NDYgQEAgdHlwZWRlZiBzdHJ1Y3QgTUNWSGFzaENvbnRleHQKIAlpbnQxNgkJaGFzaF90eXBs ZW47CS8qIHR5cGxlbiBvZiBoYXNoZWQgZGF0YSB0eXBlICovCiB9IE1DVkhhc2hDb250ZXh0 OwogCisvKiBFbnRyaWVzIGluIHRoZSBzaW1wbGVoYXNoIGhhc2ggdGFibGUgdXNlZCBieSBz Y2FsYXJhcnJheV9tY3ZfaGFzaF9tYXRjaCAqLwordHlwZWRlZiBzdHJ1Y3QgTUNWSW5IYXNo RW50cnkKK3sKKwlEYXR1bQkJdmFsdWU7CQkJLyogdGhlIHZhbHVlIHJlcHJlc2VudGVkIGJ5 IHRoaXMgZW50cnkgKi8KKwlpbnQJCQlpbmRleDsJCQkvKiBpdHMgaW5kZXggaW4gdGhlIHJl bGV2YW50IEF0dFN0YXRzU2xvdCAqLworCXVpbnQzMgkJaGFzaDsJCQkvKiBoYXNoIGNvZGUg Zm9yIHRoZSBEYXR1bSAqLworCWNoYXIJCXN0YXR1czsJCQkvKiBzdGF0dXMgY29kZSB1c2Vk IGJ5IHNpbXBsZWhhc2guaCAqLworCWludAkJCWNvdW50OwkJCS8qIG51bWJlciBvZiBvY2N1 cnJlbmNlcyBvZCBjdXJyZW50IHZhbHVlIGluCisJCQkJCQkJCSAqIHRoZSBJTi1saXN0ICov Cit9IE1DVkluSGFzaEVudHJ5OworCisvKiBwcml2YXRlX2RhdGEgZm9yIHRoZSBzaW1wbGVo YXNoIGhhc2ggdGFibGUgKi8KK3R5cGVkZWYgc3RydWN0IE1DVkluSGFzaENvbnRleHQKK3sK KwlGdW5jdGlvbkNhbGxJbmZvIGVxdWFsX2ZjaW5mbzsJLyogdGhlIGVxdWFsaXR5IGpvaW4g b3BlcmF0b3IgKi8KKwlGdW5jdGlvbkNhbGxJbmZvIGhhc2hfZmNpbmZvOwkvKiB0aGUgaGFz aCBmdW5jdGlvbiB0byB1c2UgKi8KKwlib29sCQlpbnNlcnRfbW9kZTsJLyogZG9pbmcgaW5z ZXJ0cyBvciBsb29rdXBzPyAqLworCWJvb2wJCWhhc2hfdHlwYnl2YWw7CS8qIHR5cGJ5dmFs IG9mIGhhc2hlZCBkYXRhIHR5cGUgKi8KKwlpbnQxNgkJaGFzaF90eXBsZW47CS8qIHR5cGxl biBvZiBoYXNoZWQgZGF0YSB0eXBlICovCit9IE1DVkluSGFzaENvbnRleHQ7CisKIC8qIGZv cndhcmQgcmVmZXJlbmNlICovCiB0eXBlZGVmIHN0cnVjdCBNQ1ZIYXNoVGFibGVfaGFzaCBN Q1ZIYXNoVGFibGVfaGFzaDsKK3R5cGVkZWYgc3RydWN0IE1DVkluSGFzaFRhYmxlX2hhc2gg TUNWSW5IYXNoVGFibGVfaGFzaDsKIAogLyogSG9va3MgZm9yIHBsdWdpbnMgdG8gZ2V0IGNv bnRyb2wgd2hlbiB3ZSBhc2sgZm9yIHN0YXRzICovCiBnZXRfcmVsYXRpb25fc3RhdHNfaG9v a190eXBlIGdldF9yZWxhdGlvbl9zdGF0c19ob29rID0gTlVMTDsKIGdldF9pbmRleF9zdGF0 c19ob29rX3R5cGUgZ2V0X2luZGV4X3N0YXRzX2hvb2sgPSBOVUxMOwogCiBzdGF0aWMgZG91 YmxlIGVxc2VsX2ludGVybmFsKFBHX0ZVTkNUSU9OX0FSR1MsIGJvb2wgbmVnYXRlKTsKK3N0 YXRpYyBkb3VibGUgc2NhbGFyYXJyYXlfbWN2X2hhc2hfbWF0Y2goVmFyaWFibGVTdGF0RGF0 YSAqdmFyZGF0YSwgT2lkIG9wZXJhdG9yLCBPaWQgY29sbGF0aW9uLAorCQkJCQkJCQkJCSBO b2RlICpvdGhlcl9vcCwgYm9vbCB2YXJfb25fbGVmdCwgRGF0dW0gKmVsZW1fdmFsdWVzLAor CQkJCQkJCQkJCSBib29sICplbGVtX251bGxzLCBpbnQgbnVtX2VsZW1zLCBib29sICplbGVt X2NvbnN0LAorCQkJCQkJCQkJCSBPaWQgbm9taW5hbF9lbGVtZW50X3R5cGUsIGJvb2wgdXNl T3IsIGJvb2wgaXNFcXVhbGl0eSwKKwkJCQkJCQkJCQkgYm9vbCBpc0luZXF1YWxpdHkpOwor c3RhdGljIHZvaWQgYWNjdW1fc2NhbGFyYXJyYXlfcHJvYihTZWxlY3Rpdml0eSBzMSwgYm9v bCB1c2VPciwgYm9vbCBpc0VxdWFsaXR5LAorCQkJCQkJCQkgICBib29sIGlzSW5lcXVhbGl0 eSwgZG91YmxlIG51bGxmcmFjLAorCQkJCQkJCQkgICBkb3VibGUgKnNlbGVjLCBkb3VibGUg KnMxZGlzam9pbnQpOworc3RhdGljIHVpbnQzMiBoYXNoX21jdl9pbihNQ1ZJbkhhc2hUYWJs ZV9oYXNoICp0YWIsIERhdHVtIGtleSk7CitzdGF0aWMgYm9vbCBtY3ZzX2luX2VxdWFsKE1D VkluSGFzaFRhYmxlX2hhc2ggKnRhYiwgRGF0dW0ga2V5MCwgRGF0dW0ga2V5MSk7CiBzdGF0 aWMgZG91YmxlIGVxam9pbnNlbF9pbm5lcihGbWdySW5mbyAqZXFwcm9jLCBPaWQgY29sbGF0 aW9uLAogCQkJCQkJCSAgT2lkIGhhc2hMZWZ0LCBPaWQgaGFzaFJpZ2h0LAogCQkJCQkJCSAg VmFyaWFibGVTdGF0RGF0YSAqdmFyZGF0YTEsIFZhcmlhYmxlU3RhdERhdGEgKnZhcmRhdGEy LApAQCAtMjg3LDYgKzMyNSwxOSBAQCBzdGF0aWMgZG91YmxlIGJ0Y29zdF9jb3JyZWxhdGlv bihJbmRleE9wdEluZm8gKmluZGV4LAogI2RlZmluZSBTSF9ERUNMQVJFCiAjaW5jbHVkZSAi bGliL3NpbXBsZWhhc2guaCIKIAorI2RlZmluZSBTSF9QUkVGSVgJCQkJTUNWSW5IYXNoVGFi bGUKKyNkZWZpbmUgU0hfRUxFTUVOVF9UWVBFCQkJTUNWSW5IYXNoRW50cnkKKyNkZWZpbmUg U0hfS0VZX1RZUEUJCQkJRGF0dW0KKyNkZWZpbmUgU0hfS0VZCQkJCQl2YWx1ZQorI2RlZmlu ZSBTSF9IQVNIX0tFWSh0YWIsa2V5KQloYXNoX21jdl9pbih0YWIsIGtleSkKKyNkZWZpbmUg U0hfRVFVQUwodGFiLGtleTAsa2V5MSkJbWN2c19pbl9lcXVhbCh0YWIsIGtleTAsIGtleTEp CisjZGVmaW5lIFNIX1NDT1BFCQkJCXN0YXRpYyBpbmxpbmUKKyNkZWZpbmUgU0hfU1RPUkVf SEFTSAorI2RlZmluZSBTSF9HRVRfSEFTSCh0YWIsZW50KQkoZW50KS0+aGFzaAorI2RlZmlu ZSBTSF9ERUZJTkUKKyNkZWZpbmUgU0hfREVDTEFSRQorI2luY2x1ZGUgImxpYi9zaW1wbGVo YXNoLmgiCisKIAogLyoKICAqCQllcXNlbAkJCS0gU2VsZWN0aXZpdHkgb2YgIj0iIGZvciBh bnkgZGF0YSB0eXBlcy4KQEAgLTIwMjUsNiArMjA3Niw0MCBAQCBzY2FsYXJhcnJheXNlbChQ bGFubmVySW5mbyAqcm9vdCwKIAkJCQkJCSAgZWxtbGVuLCBlbG1ieXZhbCwgZWxtYWxpZ24s CiAJCQkJCQkgICZlbGVtX3ZhbHVlcywgJmVsZW1fbnVsbHMsICZudW1fZWxlbXMpOwogCisJ CS8qCisJCSAqIFRyeSB0byBjYWxjdWxhdGUgc2VsZWN0aXZpdHkgYnkgaGFzaC1zZWFyY2gg TyhOKSBpbnN0ZWFkIG9mIE8oTl4yKQorCQkgKiBpbiBjYXNlIG9mIE1DViBtYXRjaGluZy4g IFdlIHVzZSBoYXNoLXNlYXJjaCBvbmx5IGZvciBlcXNlbCgpIGFuZAorCQkgKiBuZXFzZWwo KS4KKwkJICovCisJCWlmICgoaXNFcXVhbGl0eSB8fCBpc0luZXF1YWxpdHkpICYmICFpc19q b2luX2NsYXVzZSkKKwkJeworCQkJVmFyaWFibGVTdGF0RGF0YSB2YXJkYXRhOworCQkJTm9k ZQkgICAqb3RoZXJfb3AgPSBOVUxMOworCQkJYm9vbAkJdmFyX29uX2xlZnQ7CisKKwkJCS8q CisJCQkgKiBJZiBleHByZXNzaW9uIGlzIG5vdCB2YXJpYWJsZSA9IHNvbWV0aGluZyBvciBz b21ldGhpbmcgPQorCQkJICogdmFyaWFibGUsIHRoZW4gcHVudCBhbmQgcmV0dXJuIGEgZGVm YXVsdCBlc3RpbWF0ZS4KKwkJCSAqLworCQkJaWYgKGdldF9yZXN0cmljdGlvbl92YXJpYWJs ZShyb290LCBjbGF1c2UtPmFyZ3MsIHZhclJlbGlkLAorCQkJCQkJCQkJCSAmdmFyZGF0YSwg Jm90aGVyX29wLCAmdmFyX29uX2xlZnQpKQorCQkJeworCQkJCWJvb2wJICAgKmVsZW1fY29u c3QgPSAoYm9vbCAqKSBwYWxsb2Moc2l6ZW9mKGJvb2wpICogbnVtX2VsZW1zKTsKKworCQkJ CS8qIGFsbCBhcnJheSBlbGVtZW50cyBhcmUgQ29uc3Qgbm9kZXMgKi8KKwkJCQltZW1zZXQo ZWxlbV9jb25zdCwgdHJ1ZSwgc2l6ZW9mKGJvb2wpICogbnVtX2VsZW1zKTsKKworCQkJCXMx ID0gc2NhbGFyYXJyYXlfbWN2X2hhc2hfbWF0Y2goJnZhcmRhdGEsIG9wZXJhdG9yLCBjbGF1 c2UtPmlucHV0Y29sbGlkLCBvdGhlcl9vcCwgdmFyX29uX2xlZnQsCisJCQkJCQkJCQkJCQll bGVtX3ZhbHVlcywgZWxlbV9udWxscywgbnVtX2VsZW1zLCBlbGVtX2NvbnN0LAorCQkJCQkJ CQkJCQkJbm9taW5hbF9lbGVtZW50X3R5cGUsIHVzZU9yLCBpc0VxdWFsaXR5LCBpc0luZXF1 YWxpdHkpOworCQkJCXBmcmVlKGVsZW1fY29uc3QpOworCQkJCVJlbGVhc2VWYXJpYWJsZVN0 YXRzKHZhcmRhdGEpOworCisJCQkJaWYgKHMxID49IDAuMCkKKwkJCQkJcmV0dXJuIHMxOwor CQkJfQorCQl9CisKIAkJLyoKIAkJICogRm9yIGdlbmVyaWMgb3BlcmF0b3JzLCB3ZSBhc3N1 bWUgdGhlIHByb2JhYmlsaXR5IG9mIHN1Y2Nlc3MgaXMKIAkJICogaW5kZXBlbmRlbnQgZm9y IGVhY2ggYXJyYXkgZWxlbWVudC4gIEJ1dCBmb3IgIj0gQU5ZIiBvciAiPD4gQUxMIiwKQEAg LTIxMDAsNiArMjE4NSw3NiBAQCBzY2FsYXJhcnJheXNlbChQbGFubmVySW5mbyAqcm9vdCwK IAkJZ2V0X3R5cGxlbmJ5dmFsKGFycmF5ZXhwci0+ZWxlbWVudF90eXBlaWQsCiAJCQkJCQkm ZWxtbGVuLCAmZWxtYnl2YWwpOwogCisJCS8qCisJCSAqIFRyeSB0byBjYWxjdWxhdGUgc2Vs ZWN0aXZpdHkgYnkgaGFzaC1zZWFyY2ggTyhOKSBpbnN0ZWFkIG9mIE8oTl4yKQorCQkgKiBp biBjYXNlIG9mIE1DViBtYXRjaGluZy4gIFdlIHVzZSBoYXNoLXNlYXJjaCBvbmx5IGZvciBl cXNlbCgpIGFuZAorCQkgKiBuZXFzZWwoKS4KKwkJICovCisJCWlmICgoaXNFcXVhbGl0eSB8 fCBpc0luZXF1YWxpdHkpICYmICFpc19qb2luX2NsYXVzZSkKKwkJeworCQkJVmFyaWFibGVT dGF0RGF0YSB2YXJkYXRhOworCQkJTm9kZQkgICAqb3RoZXJfb3AgPSBOVUxMOworCQkJYm9v bAkJdmFyX29uX2xlZnQ7CisKKwkJCS8qCisJCQkgKiBJZiBleHByZXNzaW9uIGlzIG5vdCB2 YXJpYWJsZSA9IHNvbWV0aGluZyBvciBzb21ldGhpbmcgPQorCQkJICogdmFyaWFibGUsIHRo ZW4gcHVudCBhbmQgcmV0dXJuIGEgZGVmYXVsdCBlc3RpbWF0ZS4KKwkJCSAqLworCQkJaWYg KGdldF9yZXN0cmljdGlvbl92YXJpYWJsZShyb290LCBjbGF1c2UtPmFyZ3MsIHZhclJlbGlk LAorCQkJCQkJCQkJCSAmdmFyZGF0YSwgJm90aGVyX29wLCAmdmFyX29uX2xlZnQpKQorCQkJ eworCQkJCWludAkJCW51bV9lbGVtczsKKwkJCQlEYXR1bQkgICAqZWxlbV92YWx1ZXM7CisJ CQkJYm9vbAkgICAqZWxlbV9udWxsczsKKwkJCQlib29sCSAgICplbGVtX2NvbnN0OworCQkJ CUxpc3RDZWxsICAgKmxjOworCQkJCWludAkJCWkgPSAwOworCisJCQkJbnVtX2VsZW1zID0g bGlzdF9sZW5ndGgoYXJyYXlleHByLT5lbGVtZW50cyk7CisJCQkJZWxlbV92YWx1ZXMgPSAo RGF0dW0gKikgcGFsbG9jMChzaXplb2YoRGF0dW0pICogbnVtX2VsZW1zKTsKKwkJCQllbGVt X251bGxzID0gKGJvb2wgKikgcGFsbG9jMChzaXplb2YoYm9vbCkgKiBudW1fZWxlbXMpOwor CQkJCWVsZW1fY29uc3QgPSAoYm9vbCAqKSBwYWxsb2MwKHNpemVvZihib29sKSAqIG51bV9l bGVtcyk7CisKKwkJCQkvKgorCQkJCSAqIEJ1aWxkIGFycmF5cyBkZXNjcmliaW5nIEFSUkFZ W10gZWxlbWVudHM6IC0gZWxlbV92YWx1ZXM6CisJCQkJICogRGF0dW0gdmFsdWUgZm9yIENv bnN0IGVsZW1lbnRzIC0gZWxlbV9udWxsczogd2hldGhlcgorCQkJCSAqIGVsZW1lbnQgaXMg TlVMTCAtIGVsZW1fY29uc3Q6IHdoZXRoZXIgZWxlbWVudCBpcyBhIENvbnN0CisJCQkJICog bm9kZQorCQkJCSAqLworCQkJCWZvcmVhY2gobGMsIGFycmF5ZXhwci0+ZWxlbWVudHMpCisJ CQkJeworCQkJCQlOb2RlCSAgICplbGVtX3ZhbHVlID0gKE5vZGUgKikgbGZpcnN0KGxjKTsK KworCQkJCQlpZiAoSXNBKGVsZW1fdmFsdWUsIENvbnN0KSkKKwkJCQkJeworCQkJCQkJZWxl bV92YWx1ZXNbaV0gPSAoKENvbnN0ICopIGVsZW1fdmFsdWUpLT5jb25zdHZhbHVlOworCQkJ CQkJZWxlbV9udWxsc1tpXSA9ICgoQ29uc3QgKikgZWxlbV92YWx1ZSktPmNvbnN0aXNudWxs OworCQkJCQkJZWxlbV9jb25zdFtpXSA9IHRydWU7CisJCQkJCX0KKwkJCQkJZWxzZQorCQkJ CQl7CisJCQkJCQllbGVtX251bGxzW2ldID0gZmFsc2U7CisJCQkJCQllbGVtX2NvbnN0W2ld ID0gZmFsc2U7CisJCQkJCX0KKworCQkJCQlpKys7CisJCQkJfQorCisJCQkJczEgPSBzY2Fs YXJhcnJheV9tY3ZfaGFzaF9tYXRjaCgmdmFyZGF0YSwgb3BlcmF0b3IsIGNsYXVzZS0+aW5w dXRjb2xsaWQsIG90aGVyX29wLCB2YXJfb25fbGVmdCwKKwkJCQkJCQkJCQkJCWVsZW1fdmFs dWVzLCBlbGVtX251bGxzLCBudW1fZWxlbXMsIGVsZW1fY29uc3QsCisJCQkJCQkJCQkJCQlu b21pbmFsX2VsZW1lbnRfdHlwZSwgdXNlT3IsIGlzRXF1YWxpdHksIGlzSW5lcXVhbGl0eSk7 CisKKwkJCQlwZnJlZShlbGVtX3ZhbHVlcyk7CisJCQkJcGZyZWUoZWxlbV9udWxscyk7CisJ CQkJcGZyZWUoZWxlbV9jb25zdCk7CisKKwkJCQlSZWxlYXNlVmFyaWFibGVTdGF0cyh2YXJk YXRhKTsKKworCQkJCWlmIChzMSA+PSAwLjApCisJCQkJCXJldHVybiBzMTsKKwkJCX0KKwkJ fQorCiAJCS8qCiAJCSAqIFdlIHVzZSB0aGUgYXNzdW1wdGlvbiBvZiBkaXNqb2ludCBwcm9i YWJpbGl0aWVzIGhlcmUgdG9vLCBhbHRob3VnaAogCQkgKiB0aGUgb2RkcyBvZiBlcXVhbCBh cnJheSBlbGVtZW50cyBhcmUgcmF0aGVyIGhpZ2hlciBpZiB0aGUgZWxlbWVudHMKQEAgLTIy MTAsNiArMjM2NSw0MzcgQEAgc2NhbGFyYXJyYXlzZWwoUGxhbm5lckluZm8gKnJvb3QsCiAJ cmV0dXJuIHMxOwogfQogCisKKy8qCisgKiBFc3RpbWF0ZSBzZWxlY3Rpdml0eSBvZiBhIFNj YWxhckFycmF5T3BFeHByIChBTlkvQUxMKSB1c2luZyBNQ1Ygc3RhdGlzdGljcworICogd2l0 aCBoYXNoLWJhc2VkIG1hdGNoaW5nLgorICoKKyAqIFRoaXMgZnVuY3Rpb24gZm9sbG93cyB0 aGUgc2FtZSBwcm9iYWJpbGl0eSBtb2RlbCBhcyB0aGUgZ2VuZXJpYworICogU2NhbGFyQXJy YXlPcEV4cHIgc2VsZWN0aXZpdHkgY29kZSAoaW5kZXBlbmRlbnQgb3IgZGlzam9pbnQgcHJv YmFiaWxpdGllcworICogZm9yIE9SL0FORCBjb21iaW5hdGlvbnMpLCBidXQgYXR0ZW1wdHMg dG8gc3BlZWQgdXAgbWF0Y2hpbmcgYmV0d2VlbgorICogSU4tbGlzdCBlbGVtZW50cyBhbmQg dGhlIGNvbHVtbidzIG1vc3QtY29tbW9uLXZhbHVlcyAoTUNWKSBzdGF0aXN0aWNzIGJ5Cisg KiB1c2luZyBoYXNoaW5nIGluc3RlYWQgb2YgbmVzdGVkIGxvb3BzLgorICoKKyAqIE1DViBz dGF0aXN0aWNzIGFyZSB1c2VkIG9ubHkgdG8gb2J0YWluIHBlci12YWx1ZSBzZWxlY3Rpdml0 aWVzIGZvcgorICogY29uc3RhbnRzIHRoYXQgbWF0Y2ggTUNWIGVudHJpZXMuICBBbGwgcHJv YmFiaWxpdGllcyBhcmUgY29tYmluZWQgdXNpbmcKKyAqIHRoZSBzdGFuZGFyZCBBTlkvQUxM IGZvcm11bGFzLCBleGFjdGx5IGFzIGluIHRoZSBnZW5lcmljIGVzdGltYXRvci4KKyAqCisg KiBUaGUgZnVuY3Rpb24gbWF5IHJldHVybiAtMS4wIHRvIGluZGljYXRlIHRoYXQgaGFzaC1i YXNlZCBNQ1YgZXN0aW1hdGlvbgorICogaXMgbm90IGFwcGxpY2FibGUgKGZvciBleGFtcGxl LCBtaXNzaW5nIHN0YXRpc3RpY3MsIHVuc3VwcG9ydGVkIG9wZXJhdG9yLAorICogb3IgdW5h dmFpbGFibGUgaGFzaCBmdW5jdGlvbnMpLCBpbiB3aGljaCBjYXNlIHRoZSBjYWxsZXIgc2hv dWxkIGZhbGwgYmFjaworICogdG8gdGhlIGdlbmVyaWMgU2NhbGFyQXJyYXlPcEV4cHIgc2Vs ZWN0aXZpdHkgZXN0aW1hdGlvbi4KKyAqCisgKiBJbnB1dHM6CisgKgl2YXJkYXRhOiBzdGF0 aXN0aWNzIGFuZCBtZXRhZGF0YSBmb3IgdGhlIHZhcmlhYmxlIGJlaW5nIGVzdGltYXRlZAor ICoJb3BlcmF0b3I6IGVxdWFsaXR5IG9yIGluZXF1YWxpdHkgb3BlcmF0b3IgdG8gYXBwbHkK KyAqCWNvbGxhdGlvbjogT0lEIG9mIGNvbGxhdGlvbiB0byB1c2UKKyAqCW90aGVyX29wOiBl eHByZXNzaW9uIGZvciB0aGUgbm9uLXZhcmlhYmxlIHNpZGUgb2YgdGhlIGNvbXBhcmlzb24K KyAqCXZhcl9vbl9sZWZ0OiB0cnVlIGlmIHRoZSB2YXJpYWJsZSBpcyBvbiB0aGUgbGVmdCBz aWRlIG9mIHRoZSBvcGVyYXRvcgorICoJZWxlbV92YWx1ZXM6IGFycmF5IG9mIElOLWxpc3Qg ZWxlbWVudCB2YWx1ZXMKKyAqCWVsZW1fbnVsbHM6IGFycmF5IGluZGljYXRpbmcgd2hpY2gg SU4tbGlzdCBlbGVtZW50cyBhcmUgTlVMTAorICoJZWxlbV9jb25zdDogYXJyYXkgaW5kaWNh dGluZyB3aGljaCBJTi1saXN0IGVsZW1lbnRzIGFyZSBDb25zdCBub2RlcworICoJbnVtX2Vs ZW1zOiBudW1iZXIgb2YgSU4tbGlzdCBlbGVtZW50cworICoJbm9taW5hbF9lbGVtZW50X3R5 cGU6IHR5cGUgb2YgSU4tbGlzdCBlbGVtZW50cworICoJdXNlT3I6IHRydWUgaWYgZWxlbWVu dHMgYXJlIGNvbWJpbmVkIHVzaW5nIE9SIHNlbWFudGljcywgZmFsc2UgZm9yIEFORAorICoJ aXNFcXVhbGl0eTogdHJ1ZSBpZiB0aGUgb3BlcmF0b3IgYmVoYXZlcyBsaWtlIGVxdWFsaXR5 CisgKglpc0luZXF1YWxpdHk6IHRydWUgaWYgdGhlIG9wZXJhdG9yIGJlaGF2ZXMgbGlrZSBp bmVxdWFsaXR5CisgKgorICogUmVzdWx0OgorICoJU2VsZWN0aXZpdHkgZXN0aW1hdGUgaW4g dGhlIHJhbmdlIFswLjAsIDEuMF0sIG9yIC0xLjAgaWYgbm8gZXN0aW1hdGUKKyAqCWNvdWxk IGJlIHByb2R1Y2VkIGJ5IHRoaXMgZnVuY3Rpb24uCisgKgorICogTm90ZToKKyAqCVRoaXMg ZnVuY3Rpb24gYXNzdW1lcyB0aGF0IHRoZSBvcGVyYXRvcuKAmXMgc2VsZWN0aXZpdHkgYmVo YXZpb3IgbWF0Y2hlcworICoJZXFzZWwoKS9uZXFzZWwgc2VtYW50aWNzLiAgSXQgbXVzdCBu b3QgYmUgdXNlZCBmb3Igb3BlcmF0b3JzIHdpdGggY3VzdG9tCisgKglvciBub24tc3RhbmRh cmQgc2VsZWN0aXZpdHkgYmVoYXZpb3IuCisgKi8KK3N0YXRpYyBkb3VibGUKK3NjYWxhcmFy cmF5X21jdl9oYXNoX21hdGNoKFZhcmlhYmxlU3RhdERhdGEgKnZhcmRhdGEsIE9pZCBvcGVy YXRvciwgT2lkIGNvbGxhdGlvbiwKKwkJCQkJCSAgIE5vZGUgKm90aGVyX29wLCBib29sIHZh cl9vbl9sZWZ0LAorCQkJCQkJICAgRGF0dW0gKmVsZW1fdmFsdWVzLCBib29sICplbGVtX251 bGxzLCBpbnQgbnVtX2VsZW1zLCBib29sICplbGVtX2NvbnN0LAorCQkJCQkJICAgT2lkIG5v bWluYWxfZWxlbWVudF90eXBlLCBib29sIHVzZU9yLCBib29sIGlzRXF1YWxpdHksCisJCQkJ CQkgICBib29sIGlzSW5lcXVhbGl0eSkKK3sKKwlGb3JtX3BnX3N0YXRpc3RpYyBzdGF0czsK KwlBdHRTdGF0c1Nsb3Qgc3Nsb3Q7CisJRm1nckluZm8JZXFwcm9jOworCWRvdWJsZQkJc2Vs ZWMgPSAtMS4wLAorCQkJCXMxZGlzam9pbnQsCisJCQkJbnVsbGZyYWMgPSAwLjA7CisJT2lk CQkJaGFzaExlZnQgPSBJbnZhbGlkT2lkLAorCQkJCWhhc2hSaWdodCA9IEludmFsaWRPaWQs CisJCQkJb3BmdW5jb2lkOworCWJvb2wJCWhhdmVfbWN2cyA9IGZhbHNlOworCisJLyoKKwkg KiBJZiB0aGUgdmFyaWFibGUgaXMga25vd24gdG8gYmUgdW5pcXVlLCBNQ1Ygc3RhdGlzdGlj cyBkbyBub3QgcmVwcmVzZW50CisJICogYSBtZWFuaW5nZnVsIGZyZXF1ZW5jeSBkaXN0cmli dXRpb24sIHNvIHNraXAgTUNWLWJhc2VkIGVzdGltYXRpb24uCisJICovCisJaWYgKHZhcmRh dGEtPmlzdW5pcXVlICYmIHZhcmRhdGEtPnJlbCAmJiB2YXJkYXRhLT5yZWwtPnR1cGxlcyA+ PSAxLjApCisJCXJldHVybiAtMS4wOworCisJLyoKKwkgKiBGb3IgaW5lcXVhbGl0eSAoPD4s IEFMTCksIHdlIGNvbXB1dGUgcHJvYmFiaWxpdGllcyB1c2luZyB0aGUgbmVnYXRlZAorCSAq IGVxdWFsaXR5IG9wZXJhdG9yIGFuZCBsYXRlciB0cmFuc2Zvcm0gdGhlbSBhcworCSAqCisJ ICogcCh4IDw+IGMpID0gMSAtIHAoeCA9IGMpIC0gbnVsbGZyYWMKKwkgKi8KKwlpZiAoaXNJ bmVxdWFsaXR5KQorCXsKKwkJb3BlcmF0b3IgPSBnZXRfbmVnYXRvcihvcGVyYXRvcik7CisJ CWlmICghT2lkSXNWYWxpZChvcGVyYXRvcikpCisJCQlyZXR1cm4gLTEuMDsKKwl9CisKKwlv cGZ1bmNvaWQgPSBnZXRfb3Bjb2RlKG9wZXJhdG9yKTsKKwltZW1zZXQoJnNzbG90LCAwLCBz aXplb2Yoc3Nsb3QpKTsKKworCWlmIChIZWFwVHVwbGVJc1ZhbGlkKHZhcmRhdGEtPnN0YXRz VHVwbGUpKQorCXsKKwkJaWYgKHN0YXRpc3RpY19wcm9jX3NlY3VyaXR5X2NoZWNrKHZhcmRh dGEsIG9wZnVuY29pZCkpCisJCQloYXZlX21jdnMgPSBnZXRfYXR0c3RhdHNzbG90KCZzc2xv dCwgdmFyZGF0YS0+c3RhdHNUdXBsZSwKKwkJCQkJCQkJCQkgU1RBVElTVElDX0tJTkRfTUNW LCBJbnZhbGlkT2lkLAorCQkJCQkJCQkJCSBBVFRTVEFUU1NMT1RfVkFMVUVTIHwgQVRUU1RB VFNTTE9UX05VTUJFUlMpOworCX0KKworCWlmIChoYXZlX21jdnMpCisJeworCQlmbWdyX2lu Zm8ob3BmdW5jb2lkLCAmZXFwcm9jKTsKKworCQkvKgorCQkgKiBmIHRoZSBNQ1YgbGlzdCBh bmQgSU4tbGlzdCBhcmUgbGFyZ2UgZW5vdWdoLCBhbmQgdGhlIG9wZXJhdG9yCisJCSAqIHN1 cHBvcnRzIGhhc2hpbmcsIGF0dGVtcHQgdG8gdXNlIGhhc2ggZnVuY3Rpb25zIHNvIHRoYXQg TUNW4oCTSU4KKwkJICogbWF0Y2hpbmcgY2FuIGJlIGRvbmUgaW4gTyhOK00pIGluc3RlYWQg b2YgTyhOw5dNKS4KKwkJICovCisJCWlmIChzc2xvdC5udmFsdWVzICsgbnVtX2VsZW1zID49 IFNDQUxBUkFSUkFZX01DVl9IQVNIX1RIUkVTSE9MRCkKKwkJCSh2b2lkKSBnZXRfb3BfaGFz aF9mdW5jdGlvbnMob3BlcmF0b3IsICZoYXNoTGVmdCwgJmhhc2hSaWdodCk7CisJfQorCisJ aWYgKGhhdmVfbWN2cyAmJiBPaWRJc1ZhbGlkKGhhc2hMZWZ0KSAmJiBPaWRJc1ZhbGlkKGhh c2hSaWdodCkpCisJeworCQkvKiBVc2UgYSBoYXNoIHRhYmxlIHRvIHNwZWVkIHVwIHRoZSBt YXRjaGluZyAqLworCQlMT0NBTF9GQ0lORk8oZmNpbmZvLCAyKTsKKwkJTE9DQUxfRkNJTkZP KGhhc2hfZmNpbmZvLCAxKTsKKwkJTUNWSW5IYXNoVGFibGVfaGFzaCAqaGFzaFRhYmxlOwor CQlGbWdySW5mbwloYXNoX3Byb2M7CisJCU1DVkluSGFzaENvbnRleHQgaGFzaENvbnRleHQ7 CisJCWRvdWJsZQkJc3VtYWxsY29tbW9uID0gMC4wLAorCQkJCQlub25tY3Zfc2VsZWMgPSAw LjA7CisJCWJvb2wJCWlzZGVmYXVsdDsKKwkJYm9vbAkJaGFzaF9tY3Y7CisJCWRvdWJsZQkJ b3RoZXJkaXN0aW5jdDsKKwkJRGF0dW0JICAgKmFycmF5SGFzaDsKKwkJRGF0dW0JICAgKmFy cmF5UHJvYmU7CisJCWludAkJCW52YWx1ZXNIYXNoOworCQlpbnQJCQludmFsdWVzUHJvYmU7 CisJCWludAkJCW52YWx1ZXNub25tY3YgPSBudW1fZWxlbXM7CisJCWludAkJCW52YWx1ZXNu b25jb25zdCA9IDA7CisKKwkJLyogR3JhYiB0aGUgbnVsbGZyYWMgZm9yIHVzZSBiZWxvdy4g Ki8KKwkJc3RhdHMgPSAoRm9ybV9wZ19zdGF0aXN0aWMpIEdFVFNUUlVDVCh2YXJkYXRhLT5z dGF0c1R1cGxlKTsKKwkJbnVsbGZyYWMgPSBzdGF0cy0+c3RhbnVsbGZyYWM7CisKKwkJc2Vs ZWMgPSBzMWRpc2pvaW50ID0gKHVzZU9yID8gMC4wIDogMS4wKTsKKworCQlJbml0RnVuY3Rp b25DYWxsSW5mb0RhdGEoKmZjaW5mbywgJmVxcHJvYywgMiwgY29sbGF0aW9uLAorCQkJCQkJ CQkgTlVMTCwgTlVMTCk7CisJCWZjaW5mby0+YXJnc1swXS5pc251bGwgPSBmYWxzZTsKKwkJ ZmNpbmZvLT5hcmdzWzFdLmlzbnVsbCA9IGZhbHNlOworCisJCWZvciAoaW50IGkgPSAwOyBp IDwgc3Nsb3QubnZhbHVlczsgaSsrKQorCQkJc3VtYWxsY29tbW9uICs9IHNzbG90Lm51bWJl cnNbaV07CisKKwkJLyoKKwkJICogQ29tcHV0ZSB0aGUgdG90YWwgcHJvYmFiaWxpdHkgbWFz cyBvZiBhbGwgbm9uLU1DViB2YWx1ZXMuIFRoaXMgaXMKKwkJICogdGhlIHBhcnQgb2YgdGhl IGNvbHVtbiBkaXN0cmlidXRpb24gbm90IGNvdmVyZWQgYnkgTUNWcy4KKwkJICovCisJCW5v bm1jdl9zZWxlYyA9IDEuMCAtIHN1bWFsbGNvbW1vbiAtIG51bGxmcmFjOworCQlDTEFNUF9Q Uk9CQUJJTElUWShub25tY3Zfc2VsZWMpOworCisJCS8qCisJCSAqIEFwcHJveGltYXRlIHRo ZSBwZXItdmFsdWUgcHJvYmFiaWxpdHkgb2YgYSBub24tTUNWIGNvbnN0YW50IGJ5CisJCSAq IGRpdmlkaW5nIHRoZSByZW1haW5pbmcgcHJvYmFiaWxpdHkgbWFzcyBieSB0aGUgbnVtYmVy IG9mIG90aGVyCisJCSAqIGRpc3RpbmN0IHZhbHVlcy4KKwkJICovCisJCW90aGVyZGlzdGlu Y3QgPSBnZXRfdmFyaWFibGVfbnVtZGlzdGluY3QodmFyZGF0YSwgJmlzZGVmYXVsdCkgLSBz c2xvdC5ubnVtYmVyczsKKwkJaWYgKG90aGVyZGlzdGluY3QgPiAxKQorCQkJbm9ubWN2X3Nl bGVjIC89IG90aGVyZGlzdGluY3Q7CisKKwkJaWYgKHNzbG90Lm5udW1iZXJzID4gMCAmJiBu b25tY3Zfc2VsZWMgPiBzc2xvdC5udW1iZXJzW3NzbG90Lm5udW1iZXJzIC0gMV0pCisJCQlu b25tY3Zfc2VsZWMgPSBzc2xvdC5udW1iZXJzW3NzbG90Lm5udW1iZXJzIC0gMV07CisKKwkJ LyogTWFrZSBzdXJlIHdlIGJ1aWxkIHRoZSBoYXNoIHRhYmxlIG9uIHRoZSBzbWFsbGVyIGFy cmF5LiAqLworCQlpZiAoc3Nsb3QubnZhbHVlcyA8PSBudW1fZWxlbXMpCisJCXsKKwkJCWhh c2hfbWN2ID0gdHJ1ZTsKKwkJCW52YWx1ZXNIYXNoID0gc3Nsb3QubnZhbHVlczsKKwkJCW52 YWx1ZXNQcm9iZSA9IG51bV9lbGVtczsKKwkJCWFycmF5SGFzaCA9IHNzbG90LnZhbHVlczsK KwkJCWFycmF5UHJvYmUgPSBlbGVtX3ZhbHVlczsKKwkJfQorCQllbHNlCisJCXsKKwkJCWhh c2hfbWN2ID0gZmFsc2U7CisJCQludmFsdWVzSGFzaCA9IG51bV9lbGVtczsKKwkJCW52YWx1 ZXNQcm9iZSA9IHNzbG90Lm52YWx1ZXM7CisJCQlhcnJheUhhc2ggPSBlbGVtX3ZhbHVlczsK KwkJCWFycmF5UHJvYmUgPSBzc2xvdC52YWx1ZXM7CisJCX0KKworCQlmbWdyX2luZm8oaGFz aF9tY3YgPyBoYXNoTGVmdCA6IGhhc2hSaWdodCwgJmhhc2hfcHJvYyk7CisJCUluaXRGdW5j dGlvbkNhbGxJbmZvRGF0YSgqaGFzaF9mY2luZm8sICZoYXNoX3Byb2MsIDEsIGNvbGxhdGlv biwKKwkJCQkJCQkJIE5VTEwsIE5VTEwpOworCQloYXNoX2ZjaW5mby0+YXJnc1swXS5pc251 bGwgPSBmYWxzZTsKKworCQloYXNoQ29udGV4dC5lcXVhbF9mY2luZm8gPSBmY2luZm87CisJ CWhhc2hDb250ZXh0Lmhhc2hfZmNpbmZvID0gaGFzaF9mY2luZm87CisJCWhhc2hDb250ZXh0 Lmluc2VydF9tb2RlID0gdHJ1ZTsKKworCQlnZXRfdHlwbGVuYnl2YWwoaGFzaF9tY3YgPyBz c2xvdC52YWx1ZXR5cGUgOiBub21pbmFsX2VsZW1lbnRfdHlwZSwKKwkJCQkJCSZoYXNoQ29u dGV4dC5oYXNoX3R5cGxlbiwKKwkJCQkJCSZoYXNoQ29udGV4dC5oYXNoX3R5cGJ5dmFsKTsK KworCQloYXNoVGFibGUgPSBNQ1ZJbkhhc2hUYWJsZV9jcmVhdGUoQ3VycmVudE1lbW9yeUNv bnRleHQsCisJCQkJCQkJCQkJICBudmFsdWVzSGFzaCwKKwkJCQkJCQkJCQkgICZoYXNoQ29u dGV4dCk7CisKKwkJLyogQnVpbGQgYSBoYXNoIHRhYmxlIG92ZXIgdGhlIHNtYWxsZXIgaW5w dXQgc2lkZS4gKi8KKwkJZm9yIChpbnQgaSA9IDA7IGkgPCBudmFsdWVzSGFzaDsgaSsrKQor CQl7CisJCQlib29sCQlmb3VuZCA9IGZhbHNlOworCQkJTUNWSW5IYXNoRW50cnkgKmVudHJ5 OworCisJCQkvKgorCQkJICogV2hlbiBoYXNoaW5nIElOLWxpc3QgdmFsdWVzIChoYXNoX21j diA9PSBmYWxzZSksIHdlIG9ubHkgaW5zZXJ0CisJCQkgKiBjb25zdGFudCwgbm9uLU5VTEwg ZWxlbWVudHMuICBOVUxMIGFuZCBub24tQ29uc3QgZWxlbWVudHMgYXJlCisJCQkgKiBjb3Vu dGVkIHNlcGFyYXRlbHksIGJlY2F1c2UgdGhleSBjYW5ub3QgcGFydGljaXBhdGUgaW4gTUNW CisJCQkgKiBtYXRjaGluZyBhbmQgbXVzdCBiZSBoYW5kbGVkIGxhdGVyIHVzaW5nIGdlbmVy aWMgc2VsZWN0aXZpdHkKKwkJCSAqIGVzdGltYXRpb24uCisJCQkgKi8KKwkJCWlmICghaGFz aF9tY3YpCisJCQl7CisJCQkJaWYgKGVsZW1fbnVsbHNbaV0pCisJCQkJeworCQkJCQludmFs dWVzbm9ubWN2LS07CisJCQkJCWNvbnRpbnVlOworCQkJCX0KKworCQkJCWlmICghZWxlbV9j b25zdFtpXSkKKwkJCQl7CisJCQkJCW52YWx1ZXNub25tY3YtLTsKKwkJCQkJbnZhbHVlc25v bmNvbnN0Kys7CisJCQkJCWNvbnRpbnVlOworCQkJCX0KKwkJCX0KKworCQkJZW50cnkgPSBN Q1ZJbkhhc2hUYWJsZV9pbnNlcnQoaGFzaFRhYmxlLCBhcnJheUhhc2hbaV0sICZmb3VuZCk7 CisKKwkJCS8qCisJCQkgKiBlbnRyeS0+Y291bnQgdHJhY2tzIGhvdyBtYW55IHRpbWVzIHRo ZSBzYW1lIHZhbHVlIGFwcGVhcnMsIHNvCisJCQkgKiB0aGF0IGR1cGxpY2F0ZSBJTi1saXN0 IGVsZW1lbnRzIGNhbiBiZSBmb2xkZWQgaW50byB0aGUKKwkJCSAqIHByb2JhYmlsaXR5IGNh bGN1bGF0aW9uLgorCQkJICovCisJCQlpZiAobGlrZWx5KCFmb3VuZCkpCisJCQl7CisJCQkJ ZW50cnktPmluZGV4ID0gaTsKKwkJCQllbnRyeS0+Y291bnQgPSAxOworCQkJfQorCQkJZWxz ZQorCQkJCWVudHJ5LT5jb3VudCsrOworCQl9CisKKwkJaGFzaENvbnRleHQuaW5zZXJ0X21v ZGUgPSBmYWxzZTsKKwkJaWYgKGhhc2hMZWZ0ICE9IGhhc2hSaWdodCkKKwkJeworCQkJZm1n cl9pbmZvKGhhc2hfbWN2ID8gaGFzaFJpZ2h0IDogaGFzaExlZnQsICZoYXNoX3Byb2MpOwor CQkJLyogUmVzZXR0aW5nIGhhc2hfZmNpbmZvIGlzIHByb2JhYmx5IHVubmVjZXNzYXJ5LCBi dXQgYmUgc2FmZSAqLworCQkJSW5pdEZ1bmN0aW9uQ2FsbEluZm9EYXRhKCpoYXNoX2ZjaW5m bywgJmhhc2hfcHJvYywgMSwgY29sbGF0aW9uLAorCQkJCQkJCQkJIE5VTEwsIE5VTEwpOwor CQkJaGFzaF9mY2luZm8tPmFyZ3NbMF0uaXNudWxsID0gZmFsc2U7CisJCX0KKworCQlmb3Ig KGludCBpID0gMDsgaSA8IG52YWx1ZXNQcm9iZTsgaSsrKQorCQl7CisJCQlNQ1ZJbkhhc2hF bnRyeSAqZW50cnk7CisJCQlTZWxlY3Rpdml0eSBzMTsKKwkJCWludAkJCW52YWx1ZXNtY3Y7 CisKKwkJCS8qCisJCQkgKiBXaGVuIHByb2Jpbmcgd2l0aCBJTi1saXN0IGVsZW1lbnRzLCBp Z25vcmUgTlVMTHMgYW5kIG5vbi1Db25zdAorCQkJICogZXhwcmVzc2lvbnM6IHRoZXkgY2Fu bm90IGJlIG1hdGNoZWQgYWdhaW5zdCBNQ1ZzIGFuZCB3aWxsIGJlCisJCQkgKiBhY2NvdW50 ZWQgZm9yIGxhdGVyIGJ5IGdlbmVyaWMgZXN0aW1hdGlvbi4KKwkJCSAqLworCQkJaWYgKGhh c2hfbWN2KQorCQkJeworCQkJCWlmIChlbGVtX251bGxzW2ldKQorCQkJCXsKKwkJCQkJbnZh bHVlc25vbm1jdi0tOworCQkJCQljb250aW51ZTsKKwkJCQl9CisKKwkJCQlpZiAoIWVsZW1f Y29uc3RbaV0pCisJCQkJeworCQkJCQludmFsdWVzbm9ubWN2LS07CisJCQkJCW52YWx1ZXNu b25jb25zdCsrOworCQkJCQljb250aW51ZTsKKwkJCQl9CisJCQl9CisKKwkJCWVudHJ5ID0g TUNWSW5IYXNoVGFibGVfbG9va3VwKGhhc2hUYWJsZSwgYXJyYXlQcm9iZVtpXSk7CisKKwkJ CS8qCisJCQkgKiBJZiBmb3VuZCwgb2J0YWluIGl0cyBNQ1YgZnJlcXVlbmN5IGFuZCByZW1l bWJlciBob3cgbWFueSB2YWx1ZXMKKwkJCSAqIG9uIHRoZSBoYXNoZWQgc2lkZSBtYXAgdG8g dGhpcyBlbnRyeS4KKwkJCSAqLworCQkJaWYgKGVudHJ5ICE9IE5VTEwpCisJCQl7CisJCQkJ czEgPSBoYXNoX21jdiA/IHNzbG90Lm51bWJlcnNbZW50cnktPmluZGV4XQorCQkJCQk6IHNz bG90Lm51bWJlcnNbaV07CisKKwkJCQludmFsdWVzbWN2ID0gZW50cnktPmNvdW50OworCisJ CQkJLyogTWF0Y2hlZCB2YWx1ZXMgYXJlIG5vIGxvbmdlciBjb25zaWRlcmVkIG5vbi1NQ1Yg Ki8KKwkJCQludmFsdWVzbm9ubWN2IC09IG52YWx1ZXNtY3Y7CisJCQl9CisJCQllbHNlCisJ CQl7CisJCQkJLyogTm8gTUNWIG1hdGNoIGZvciB0aGlzIHZhbHVlICovCisJCQkJY29udGlu dWU7CisJCQl9CisKKwkJCS8qCisJCQkgKiBGb2xkIHRoaXMgdmFsdWUncyBwcm9iYWJpbGl0 eSBpbnRvIHRoZSBydW5uaW5nIEFOWS9BTEwKKwkJCSAqIHNlbGVjdGl2aXR5IGVzdGltYXRl IG9uY2UgZm9yIGVhY2ggb2NjdXJyZW5jZS4KKwkJCSAqLworCQkJZm9yIChpbnQgaiA9IDA7 IGogPCBudmFsdWVzbWN2OyBqKyspCisJCQkJYWNjdW1fc2NhbGFyYXJyYXlfcHJvYihzMSwg dXNlT3IsIGlzRXF1YWxpdHksIGlzSW5lcXVhbGl0eSwKKwkJCQkJCQkJCSAgIG51bGxmcmFj LCAmc2VsZWMsICZzMWRpc2pvaW50KTsKKwkJfQorCisJCS8qCisJCSAqIEFjY291bnQgZm9y IGNvbnN0YW50IElOLWxpc3QgdmFsdWVzIHRoYXQgZGlkIG5vdCBtYXRjaCBhbnkgTUNWLgor CQkgKgorCQkgKiBFYWNoIHN1Y2ggdmFsdWUgaXMgYXNzdW1lZCB0byBoYXZlIHByb2JhYmls aXR5ID0gbm9ubWN2X3NlbGVjLAorCQkgKiBkZXJpdmVkIGZyb20gdGhlIHJlbWFpbmluZyAo bm9uLU1DVikgcHJvYmFiaWxpdHkgbWFzcy4KKwkJICovCisJCWZvciAoaW50IGkgPSAwOyBp IDwgbnZhbHVlc25vbm1jdjsgaSsrKQorCQkJYWNjdW1fc2NhbGFyYXJyYXlfcHJvYihub25t Y3Zfc2VsZWMsIHVzZU9yLCBpc0VxdWFsaXR5LCBpc0luZXF1YWxpdHksCisJCQkJCQkJCSAg IG51bGxmcmFjLCAmc2VsZWMsICZzMWRpc2pvaW50KTsKKworCQkvKgorCQkgKiBBY2NvdW50 IGZvciBub24tQ29uc3QgSU4tbGlzdCBlbGVtZW50cy4KKwkJICoKKwkJICogVGhlc2UgdmFs dWVzIGNhbm5vdCBiZSBtYXRjaGVkIGFnYWluc3QgTUNWcywgc28gd2UgcmVseSBvbiB0aGUK KwkJICogb3BlcmF0b3IncyBnZW5lcmljIHNlbGVjdGl2aXR5IGVzdGltYXRvciBmb3IgZWFj aCBvZiB0aGVtLgorCQkgKi8KKwkJZm9yIChpbnQgaSA9IDA7IGkgPCBudmFsdWVzbm9uY29u c3Q7IGkrKykKKwkJeworCQkJU2VsZWN0aXZpdHkgczEgPSB2YXJfZXFfbm9uX2NvbnN0KHZh cmRhdGEsIG9wZXJhdG9yLCBjb2xsYXRpb24sCisJCQkJCQkJCQkJCSAgb3RoZXJfb3AsIHZh cl9vbl9sZWZ0LCBpc0luZXF1YWxpdHkpOworCisJCQlhY2N1bV9zY2FsYXJhcnJheV9wcm9i KHMxLCB1c2VPciwgaXNFcXVhbGl0eSwgaXNJbmVxdWFsaXR5LAorCQkJCQkJCQkgICBudWxs ZnJhYywgJnNlbGVjLCAmczFkaXNqb2ludCk7CisJCX0KKworCQkvKgorCQkgKiBGb3IgPSBB Tlkgb3IgPD4gQUxMLCBpZiB0aGUgSU4tbGlzdCBlbGVtZW50cyBhcmUgYXNzdW1lZCBkaXN0 aW5jdCwKKwkJICogdGhlIGV2ZW50cyBhcmUgZGlzam9pbnQgYW5kIHRoZSB0b3RhbCBwcm9i YWJpbGl0eSBpcyB0aGUgc3VtIG9mCisJCSAqIGluZGl2aWR1YWwgcHJvYmFiaWxpdGllcy4g IFVzZSB0aGF0IGVzdGltYXRlIGlmIGl0IGxpZXMgaW4gWzAsMV0uCisJCSAqLworCQlpZiAo KHVzZU9yID8gaXNFcXVhbGl0eSA6IGlzSW5lcXVhbGl0eSkgJiYKKwkJCXMxZGlzam9pbnQg Pj0gMC4wICYmIHMxZGlzam9pbnQgPD0gMS4wKQorCQkJc2VsZWMgPSBzMWRpc2pvaW50Owor CisJCUNMQU1QX1BST0JBQklMSVRZKHNlbGVjKTsKKworCQlNQ1ZJbkhhc2hUYWJsZV9kZXN0 cm95KGhhc2hUYWJsZSk7CisJCWZyZWVfYXR0c3RhdHNzbG90KCZzc2xvdCk7CisJfQorCisJ cmV0dXJuIHNlbGVjOworfQorCisvKgorICogQWNjdW11bGF0ZSB0aGUgc2VsZWN0aXZpdHkg Y29udHJpYnV0aW9uIG9mIGEgc2luZ2xlIGFycmF5IGVsZW1lbnQKKyAqIGludG8gdGhlIHJ1 bm5pbmcgU2NhbGFyQXJyYXlPcEV4cHIgc2VsZWN0aXZpdHkgZXN0aW1hdGUuCisgKi8KK3N0 YXRpYyB2b2lkCithY2N1bV9zY2FsYXJhcnJheV9wcm9iKFNlbGVjdGl2aXR5IHMxLAorCQkJ CQkgICBib29sIHVzZU9yLAorCQkJCQkgICBib29sIGlzRXF1YWxpdHksCisJCQkJCSAgIGJv b2wgaXNJbmVxdWFsaXR5LAorCQkJCQkgICBkb3VibGUgbnVsbGZyYWMsCisJCQkJCSAgIGRv dWJsZSAqc2VsZWMsCisJCQkJCSAgIGRvdWJsZSAqczFkaXNqb2ludCkKK3sKKwlTZWxlY3Rp dml0eSBzMiA9IHMxOworCisJaWYgKGlzSW5lcXVhbGl0eSkKKwkJczIgPSAxLjAgLSBzMiAt IG51bGxmcmFjOworCisJQ0xBTVBfUFJPQkFCSUxJVFkoczIpOworCisJaWYgKHVzZU9yKQor CXsKKwkJKnNlbGVjID0gKnNlbGVjICsgczIgLSAoKnNlbGVjKSAqIHMyOworCQlpZiAoaXNF cXVhbGl0eSkKKwkJCSpzMWRpc2pvaW50ICs9IHMyOworCX0KKwllbHNlCisJeworCQkqc2Vs ZWMgPSAoKnNlbGVjKSAqIHMyOworCQlpZiAoaXNJbmVxdWFsaXR5KQorCQkJKnMxZGlzam9p bnQgKz0gczIgLSAxLjA7CisJfQorfQorCisvKgorICogU3VwcG9ydCBmdW5jdGlvbnMgZm9y IHRoZSBoYXNoIHRhYmxlcyB1c2VkIGJ5IGVxam9pbnNlbF9maW5kX21hdGNoZXMKKyAqLwor c3RhdGljIHVpbnQzMgoraGFzaF9tY3ZfaW4oTUNWSW5IYXNoVGFibGVfaGFzaCAqdGFiLCBE YXR1bSBrZXkpCit7CisJTUNWSW5IYXNoQ29udGV4dCAqY29udGV4dCA9IChNQ1ZJbkhhc2hD b250ZXh0ICopIHRhYi0+cHJpdmF0ZV9kYXRhOworCUZ1bmN0aW9uQ2FsbEluZm8gZmNpbmZv ID0gY29udGV4dC0+aGFzaF9mY2luZm87CisJRGF0dW0JCWZyZXN1bHQ7CisKKwlmY2luZm8t PmFyZ3NbMF0udmFsdWUgPSBrZXk7CisJZmNpbmZvLT5pc251bGwgPSBmYWxzZTsKKwlmcmVz dWx0ID0gRnVuY3Rpb25DYWxsSW52b2tlKGZjaW5mbyk7CisJQXNzZXJ0KCFmY2luZm8tPmlz bnVsbCk7CisJcmV0dXJuIERhdHVtR2V0VUludDMyKGZyZXN1bHQpOworfQorCitzdGF0aWMg Ym9vbAorbWN2c19pbl9lcXVhbChNQ1ZJbkhhc2hUYWJsZV9oYXNoICp0YWIsIERhdHVtIGtl eTAsIERhdHVtIGtleTEpCit7CisJTUNWSW5IYXNoQ29udGV4dCAqY29udGV4dCA9IChNQ1ZJ bkhhc2hDb250ZXh0ICopIHRhYi0+cHJpdmF0ZV9kYXRhOworCisJaWYgKGNvbnRleHQtPmlu c2VydF9tb2RlKQorCXsKKwkJLyoKKwkJICogRHVyaW5nIHRoZSBpbnNlcnRpb24gc3RlcCwg YW55IGNvbXBhcmlzb25zIHdpbGwgYmUgYmV0d2VlbiB0d28KKwkJICogRGF0dW1zIG9mIHRo ZSBoYXNoIHRhYmxlJ3MgZGF0YSB0eXBlLCBzbyBpZiB0aGUgZ2l2ZW4gb3BlcmF0b3IgaXMK KwkJICogY3Jvc3MtdHlwZSBpdCB3aWxsIGJlIHRoZSB3cm9uZyB0aGluZyB0byB1c2UuICBG b3J0dW5hdGVseSwgd2UgY2FuCisJCSAqIHVzZSBkYXR1bV9pbWFnZV9lcSBpbnN0ZWFkLiAg VGhlIE1DViB2YWx1ZXMgc2hvdWxkIGFsbCBiZSBkaXN0aW5jdAorCQkgKiBhbnl3YXksIHNv IGl0J3MgbW9zdGx5IHByby1mb3JtYSB0byBjb21wYXJlIHRoZW0gYXQgYWxsLgorCQkgKi8K KwkJcmV0dXJuIGRhdHVtX2ltYWdlX2VxKGtleTAsIGtleTEsCisJCQkJCQkJICBjb250ZXh0 LT5oYXNoX3R5cGJ5dmFsLCBjb250ZXh0LT5oYXNoX3R5cGxlbik7CisJfQorCWVsc2UKKwl7 CisJCUZ1bmN0aW9uQ2FsbEluZm8gZmNpbmZvID0gY29udGV4dC0+ZXF1YWxfZmNpbmZvOwor CQlEYXR1bQkJZnJlc3VsdDsKKworCQlmY2luZm8tPmFyZ3NbMF0udmFsdWUgPSBrZXkwOwor CQlmY2luZm8tPmFyZ3NbMV0udmFsdWUgPSBrZXkxOworCQlmY2luZm8tPmlzbnVsbCA9IGZh bHNlOworCQlmcmVzdWx0ID0gRnVuY3Rpb25DYWxsSW52b2tlKGZjaW5mbyk7CisJCXJldHVy biAoIWZjaW5mby0+aXNudWxsICYmIERhdHVtR2V0Qm9vbChmcmVzdWx0KSk7CisJfQorfQor CiAvKgogICogRXN0aW1hdGUgbnVtYmVyIG9mIGVsZW1lbnRzIGluIHRoZSBhcnJheSB5aWVs ZGVkIGJ5IGFuIGV4cHJlc3Npb24uCiAgKgpkaWZmIC0tZ2l0IGEvc3JjL3Rvb2xzL3BnaW5k ZW50L3R5cGVkZWZzLmxpc3QgYi9zcmMvdG9vbHMvcGdpbmRlbnQvdHlwZWRlZnMubGlzdApp bmRleCBkZGJlNGM2NDk3MS4uNDhiODg2YzJhZTQgMTAwNjQ0Ci0tLSBhL3NyYy90b29scy9w Z2luZGVudC90eXBlZGVmcy5saXN0CisrKyBiL3NyYy90b29scy9wZ2luZGVudC90eXBlZGVm cy5saXN0CkBAIC0xNjcxLDYgKzE2NzEsOSBAQCBNQnVmCiBNQ1ZIYXNoQ29udGV4dAogTUNW SGFzaEVudHJ5CiBNQ1ZIYXNoVGFibGVfaGFzaAorTUNWSW5IYXNoQ29udGV4dAorTUNWSW5I YXNoRW50cnkKK01DVkluSGFzaFRhYmxlX2hhc2gKIE1DVkl0ZW0KIE1DVkxpc3QKIE1FTU9S WV9CQVNJQ19JTkZPUk1BVElPTgotLSAKMi4zNC4xCgo= --------------0IdV92Ix49zcby3y6J1wKa31--