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 1vaJy6-006tvU-03 for pgsql-hackers@arkaria.postgresql.org; Mon, 29 Dec 2025 20:35:55 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vaJy2-000e1x-2K for pgsql-hackers@arkaria.postgresql.org; Mon, 29 Dec 2025 20:35:51 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vaJy2-000e1n-0Z for pgsql-hackers@lists.postgresql.org; Mon, 29 Dec 2025 20:35:51 +0000 Received: from forward103b.mail.yandex.net ([178.154.239.150]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vaJxz-003S83-1Z for pgsql-hackers@lists.postgresql.org; Mon, 29 Dec 2025 20:35:50 +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 forward103b.mail.yandex.net (Yandex) with ESMTPS id 35BBBC003C; Mon, 29 Dec 2025 23:35:45 +0300 (MSK) Received: by mail-nwsmtp-smtp-production-main-87.sas.yp-c.yandex.net (smtp/Yandex) with ESMTPSA id hZoQQUYGu4Y0-7jauEdNx; Mon, 29 Dec 2025 23:35:44 +0300 X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tantorlabs.com; s=mail; t=1767040544; bh=wBT/vDy+A1z12zj6HvNZADLuLsatRtqSVUoeqAG+GqY=; h=Subject:To:Message-ID:Date:From; b=wXHFXcHDfvwxdCrW33Dgi+lLTMUJFfdW1dGGBrfn0UQR5W9yFVRc7V9aykyP8z23V pOOW8cSesVkgsxVTj33YjXRgs+zw20IrOk1pUAeaTwLBezel64GawxUA0UaMuytGHH IjnTxUEBca2lVPpExQucISCBvone1+uHPZA2I+0Q= Authentication-Results: mail-nwsmtp-smtp-production-main-87.sas.yp-c.yandex.net; dkim=pass header.i=@tantorlabs.com Content-Type: multipart/mixed; boundary="------------xmkzAvEO1Yaj0ARXCVW6G3KF" Message-ID: <7db341e0-fbc6-4ec5-922c-11fdafe7be12@tantorlabs.com> Date: Mon, 29 Dec 2025 23:35:43 +0300 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Content-Language: en-US To: PostgreSQL Hackers , David Geier From: Ilia Evdokimov Subject: Hash-based MCV matching for large IN-lists 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. --------------xmkzAvEO1Yaj0ARXCVW6G3KF Content-Type: multipart/alternative; boundary="------------c6NZocTTTR7naO47zKiZAdhZ" --------------c6NZocTTTR7naO47zKiZAdhZ Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Hi hackers, When estimating selectivity for ScalarArrayOpExpr (IN, ANY, ALL) and MCV statistics are available for the column, the planner currently matches IN-list elements against the MCV array using nested loop. For large IN-list and large MCV arrays this results in O(N*M) behavior, which can become unnecessarily expensive during planning. Thanks to David for pointing out this case [0] This patch introduces a hash-based matching path, analogous to what is already done for MCV matching in join selectivity estimation (057012b commit). Instead of linearly scanning the MCV array for each IN-list element, we build a hash table and probe it to identify matches. The hash table is built over the MCV values, not over the IN-list. The IN-list may contain NULLs, non-Const expressions, and duplicate values, whereas the MCV list is guaranteed to contain distinct, non-NULL values and represents the statistically meaningful domain we are matching against. Hashing the MCVs therefore avoids duplicate work and directly supports selectivity estimation. For each IN-list element, if a matching MCV is found, we add the corresponding MCV frequency to the selectivity estimate. If no match is found, the remaining selectivity is estimated in the same way as the existing non-MCV path (similar to var_eq_const when the constant is not present in the MCV list). The hash-based path is enabled only when both a sufficiently large IN-list and an MCV list are present, and suitable hash functions exist for the equality operator. The threshold is currently the same as the one used for join MCV hashing, since the underlying algorithmic tradeoffs are similar. Example: CREATE TABLE t (x int); INSERT INTO t SELECT x % 10000 FROM generate_series(1, 3000000) x; ALTER TABLE t ALTER COLUMN x SET STATISTICS 10000; ANALYZE t; Before patch: EXPLAIN (SUMMARY) SELECT * FROM t WHERE x IN (1,2,...,2000); Seq Scan on t  (cost=5.00..58280.00 rows=600000 width=4)    Filter: (x = ANY ('{1,2,...,2000}'::integer[])) * Planning Time: 57.137 ms* (3 rows) After patch: EXPLAIN (SUMMARY) SELECT * FROM t WHERE x IN (1,2,...,2000); Seq Scan on t  (cost=5.00..58280.00 rows=600000 width=4)    Filter: (x = ANY ('{1,2,...,2000}'::integer[])) * Planning Time: 0.558 ms* (3 rows) Comments, suggestions, and alternative approaches are welcome! [0]: https://www.postgresql.org/message-id/b6316b99-565b-4c89-aa08-6aea51f54526%40gmail.com -- Best regards, Ilia Evdokimov, Tantor Labs LLC, https://tantorlabs.com/ --------------c6NZocTTTR7naO47zKiZAdhZ Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit

Hi hackers,

When estimating selectivity for ScalarArrayOpExpr (IN, ANY, ALL) and MCV statistics are available for the column, the planner currently matches IN-list elements against the MCV array using nested loop. For large IN-list and large MCV arrays this results in O(N*M) behavior, which can become unnecessarily expensive during planning.

Thanks to David for pointing out this case [0]

This patch introduces a hash-based matching path, analogous to what is already done for MCV matching in join selectivity estimation (057012b commit). Instead of linearly scanning the MCV array for each IN-list element, we build a hash table and probe it to identify matches.

The hash table is built over the MCV values, not over the IN-list. The IN-list may contain NULLs, non-Const expressions, and duplicate values, whereas the MCV list is guaranteed to contain distinct, non-NULL values and represents the statistically meaningful domain we are matching against. Hashing the MCVs therefore avoids duplicate work and directly supports selectivity estimation.

For each IN-list element, if a matching MCV is found, we add the corresponding MCV frequency to the selectivity estimate. If no match is found, the remaining selectivity is estimated in the same way as the existing non-MCV path (similar to var_eq_const when the constant is not present in the MCV list).

The hash-based path is enabled only when both a sufficiently large IN-list and an MCV list are present, and suitable hash functions exist for the equality operator. The threshold is currently the same as the one used for join MCV hashing, since the underlying algorithmic tradeoffs are similar.

Example:

CREATE TABLE t (x int);
INSERT INTO t SELECT x % 10000 FROM generate_series(1, 3000000) x;
ALTER TABLE t ALTER COLUMN x SET STATISTICS 10000;
ANALYZE t;

Before patch:
EXPLAIN (SUMMARY) SELECT * FROM t WHERE x IN (1,2,...,2000);
Seq Scan on t  (cost=5.00..58280.00 rows=600000 width=4)
   Filter: (x = ANY ('{1,2,...,2000}'::integer[]))
 Planning Time: 57.137 ms
(3 rows)

After patch:
EXPLAIN (SUMMARY) SELECT * FROM t WHERE x IN (1,2,...,2000);
Seq Scan on t  (cost=5.00..58280.00 rows=600000 width=4)
   Filter: (x = ANY ('{1,2,...,2000}'::integer[]))
 Planning Time: 0.558 ms
(3 rows)

Comments, suggestions, and alternative approaches are welcome!

[0]: https://www.postgresql.org/message-id/b6316b99-565b-4c89-aa08-6aea51f54526%40gmail.com

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

--------------c6NZocTTTR7naO47zKiZAdhZ-- --------------xmkzAvEO1Yaj0ARXCVW6G3KF Content-Type: text/x-patch; charset=UTF-8; name="v1-0001-Use-hash-based-matching-for-MCVs-in-ScalarArrayOp.patch" Content-Disposition: attachment; filename*0="v1-0001-Use-hash-based-matching-for-MCVs-in-ScalarArrayOp.pa"; filename*1="tch" Content-Transfer-Encoding: base64 RnJvbSA1NzY5NWNlMzMwYjc1OGZjMWFjMTY1YzljOTZjMGE0ZGQzOTdiNWQwIE1vbiBTZXAg MTcgMDA6MDA6MDAgMjAwMQpGcm9tOiBFdmRva2ltb3YgSWxpYSA8aWx5YS5ldmRva2ltb3ZA dGFudG9ybGFicy5jb20+CkRhdGU6IE1vbiwgMjkgRGVjIDIwMjUgMjM6Mjg6NTEgKzAzMDAK U3ViamVjdDogW1BBVENIIHYxXSBVc2UgaGFzaC1iYXNlZCBtYXRjaGluZyBmb3IgTUNWcyBp biBTY2FsYXJBcnJheU9wRXhwcgogc2VsZWN0aXZpdHkKCldoZW4gZXN0aW1hdGluZyBzZWxl Y3Rpdml0eSBmb3IgU2NhbGFyQXJyYXlPcEV4cHIgKElOIC8gQU5ZIC8gQUxMKSB3aXRoCmF2 YWlsYWJsZSBNQ1Ygc3RhdGlzdGljcywgdGhlIHBsYW5uZXIgY3VycmVudGx5IG1hdGNoZXMg SU4tbGlzdCBlbGVtZW50cwphZ2FpbnN0IHRoZSBNQ1YgYXJyYXkgdXNpbmcgYSBuZXN0ZWQg bG9vcCwgcmVzdWx0aW5nIGluIE8oTipNKSBiZWhhdmlvcgpmb3IgbGFyZ2UgSU4tbGlzdHMg YW5kIE1DViBsaXN0cy4KCkludHJvZHVjZSBhIGhhc2gtYmFzZWQgbWF0Y2hpbmcgcGF0aCwg YW5hbG9nb3VzIHRvIHRoZSBvbmUgdXNlZCBmb3IgTUNWCm1hdGNoaW5nIGluIGpvaW4gc2Vs ZWN0aXZpdHkgZXN0aW1hdGlvbi4gIEJ1aWxkIGEgaGFzaCB0YWJsZSBvdmVyIHRoZSBNQ1YK dmFsdWVzIGFuZCBwcm9iZSBpdCBmb3IgZWFjaCBJTi1saXN0IGVsZW1lbnQsIGF2b2lkaW5n IHJlcGVhdGVkIGxpbmVhcgpzY2FucyBvZiB0aGUgTUNWIGFycmF5LgoKVGhlIGhhc2ggdGFi bGUgaXMgYnVpbHQgb3ZlciB0aGUgTUNWIGxpc3QgcmF0aGVyIHRoYW4gdGhlIElOLWxpc3Qs IHNpbmNlCk1DVnMgYXJlIGd1YXJhbnRlZWQgdG8gYmUgZGlzdGluY3QgYW5kIG5vbi1OVUxM LCB3aGlsZSBJTi1saXN0cyBtYXkKY29udGFpbiBkdXBsaWNhdGVzLCBOVUxMcywgb3Igbm9u LUNvbnN0IGV4cHJlc3Npb25zLgoKVGhlIGhhc2gtYmFzZWQgcGF0aCBpcyBlbmFibGVkIG9u bHkgd2hlbiBib3RoIGEgc3VmZmljaWVudGx5IGxhcmdlCklOLWxpc3QgYW5kIGFuIE1DViBs aXN0IGFyZSBwcmVzZW50LCBhbmQgc3VpdGFibGUgaGFzaCBmdW5jdGlvbnMgZXhpc3QKZm9y IHRoZSBlcXVhbGl0eSBvcGVyYXRvci4KLS0tCiBzcmMvYmFja2VuZC91dGlscy9hZHQvc2Vs ZnVuY3MuYyB8IDM5MCArKysrKysrKysrKysrKysrKysrKysrKysrKysrKystCiBzcmMvdG9v bHMvcGdpbmRlbnQvdHlwZWRlZnMubGlzdCB8ICAgMyArCiAyIGZpbGVzIGNoYW5nZWQsIDM5 MiBpbnNlcnRpb25zKCspLCAxIGRlbGV0aW9uKC0pCgpkaWZmIC0tZ2l0IGEvc3JjL2JhY2tl bmQvdXRpbHMvYWR0L3NlbGZ1bmNzLmMgYi9zcmMvYmFja2VuZC91dGlscy9hZHQvc2VsZnVu Y3MuYwppbmRleCBhOTk2ZjBjNDkzOS4uZmNkZjNiN2FjMWUgMTAwNjQ0Ci0tLSBhL3NyYy9i YWNrZW5kL3V0aWxzL2FkdC9zZWxmdW5jcy5jCisrKyBiL3NyYy9iYWNrZW5kL3V0aWxzL2Fk dC9zZWxmdW5jcy5jCkBAIC0xNDYsNyArMTQ2LDcgQEAKIC8qCiAgKiBJbiBwcm9kdWN0aW9u IGJ1aWxkcywgc3dpdGNoIHRvIGhhc2gtYmFzZWQgTUNWIG1hdGNoaW5nIHdoZW4gdGhlIGxp c3RzIGFyZQogICogbGFyZ2UgZW5vdWdoIHRvIGFtb3J0aXplIGhhc2ggc2V0dXAgY29zdC4g IChUaGlzIHRocmVzaG9sZCBpcyBjb21wYXJlZCB0bwotICogdGhlIHN1bSBvZiB0aGUgbGVu Z3RocyBvZiB0aGUgdHdvIE1DViBsaXN0cy4gIFRoaXMgaXMgc2ltcGxpc3RpYyBidXQgc2Vl bXMKKyAqIHRoZSBzdW0gb2YgdGhlIGxlbmd0aHMgb2YgdGhlIHR3byBsaXN0cy4gIFRoaXMg aXMgc2ltcGxpc3RpYyBidXQgc2VlbXMKICAqIHRvIHdvcmsgd2VsbCBlbm91Z2guKSAgSW4g ZGVidWcgYnVpbGRzLCB3ZSB1c2UgYSBzbWFsbGVyIHRocmVzaG9sZCBzbyB0aGF0CiAgKiB0 aGUgcmVncmVzc2lvbiB0ZXN0cyBjb3ZlciBib3RoIHBhdGhzIHdlbGwuCiAgKi8KQEAgLTE1 Niw2ICsxNTYsMTIgQEAKICNkZWZpbmUgRVFKT0lOU0VMX01DVl9IQVNIX1RIUkVTSE9MRCAy MAogI2VuZGlmCiAKKyNpZm5kZWYgVVNFX0FTU0VSVF9DSEVDS0lORworI2RlZmluZSBTQ0FM QVJBUlJBWV9NQ1ZfSEFTSF9USFJFU0hPTEQgMjAwCisjZWxzZQorI2RlZmluZSBTQ0FMQVJB UlJBWV9NQ1ZfSEFTSF9USFJFU0hPTEQgMjAKKyNlbmRpZgorCiAvKiBFbnRyaWVzIGluIHRo ZSBzaW1wbGVoYXNoIGhhc2ggdGFibGUgdXNlZCBieSBlcWpvaW5zZWxfZmluZF9tYXRjaGVz ICovCiB0eXBlZGVmIHN0cnVjdCBNQ1ZIYXNoRW50cnkKIHsKQEAgLTE3NiwxNCArMTgyLDQw IEBAIHR5cGVkZWYgc3RydWN0IE1DVkhhc2hDb250ZXh0CiAJaW50MTYJCWhhc2hfdHlwbGVu OwkvKiB0eXBsZW4gb2YgaGFzaGVkIGRhdGEgdHlwZSAqLwogfSBNQ1ZIYXNoQ29udGV4dDsK IAorLyogRW50cmllcyBpbiB0aGUgc2ltcGxlaGFzaCBoYXNoIHRhYmxlIHVzZWQgYnkgc2Nh bGFyYXJyYXlfbWN2X2hhc2hfbWF0Y2ggKi8KK3R5cGVkZWYgc3RydWN0IE1DVkluSGFzaEVu dHJ5Cit7CisJRGF0dW0JCXZhbHVlOwkJCS8qIHRoZSB2YWx1ZSByZXByZXNlbnRlZCBieSB0 aGlzIGVudHJ5ICovCisJaW50CQkJaW5kZXg7CQkJLyogaXRzIGluZGV4IGluIHRoZSByZWxl dmFudCBBdHRTdGF0c1Nsb3QgKi8KKwl1aW50MzIJCWhhc2g7CQkJLyogaGFzaCBjb2RlIGZv ciB0aGUgRGF0dW0gKi8KKwljaGFyCQlzdGF0dXM7CQkJLyogc3RhdHVzIGNvZGUgdXNlZCBi eSBzaW1wbGVoYXNoLmggKi8KK30gTUNWSW5IYXNoRW50cnk7CisKKy8qIHByaXZhdGVfZGF0 YSBmb3IgdGhlIHNpbXBsZWhhc2ggaGFzaCB0YWJsZSAqLwordHlwZWRlZiBzdHJ1Y3QgTUNW SW5IYXNoQ29udGV4dAoreworCUZ1bmN0aW9uQ2FsbEluZm8gZXF1YWxfZmNpbmZvOwkvKiB0 aGUgZXF1YWxpdHkgam9pbiBvcGVyYXRvciAqLworCUZ1bmN0aW9uQ2FsbEluZm8gaGFzaF9m Y2luZm87CS8qIHRoZSBoYXNoIGZ1bmN0aW9uIHRvIHVzZSAqLworCWJvb2wJCWluc2VydF9t b2RlOwkvKiBkb2luZyBpbnNlcnRzIG9yIGxvb2t1cHM/ICovCisJYm9vbAkJaGFzaF90eXBi eXZhbDsJLyogdHlwYnl2YWwgb2YgaGFzaGVkIGRhdGEgdHlwZSAqLworCWludDE2CQloYXNo X3R5cGxlbjsJLyogdHlwbGVuIG9mIGhhc2hlZCBkYXRhIHR5cGUgKi8KK30gTUNWSW5IYXNo Q29udGV4dDsKKwogLyogZm9yd2FyZCByZWZlcmVuY2UgKi8KIHR5cGVkZWYgc3RydWN0IE1D Vkhhc2hUYWJsZV9oYXNoIE1DVkhhc2hUYWJsZV9oYXNoOwordHlwZWRlZiBzdHJ1Y3QgTUNW SW5IYXNoVGFibGVfaGFzaCBNQ1ZJbkhhc2hUYWJsZV9oYXNoOwogCiAvKiBIb29rcyBmb3Ig cGx1Z2lucyB0byBnZXQgY29udHJvbCB3aGVuIHdlIGFzayBmb3Igc3RhdHMgKi8KIGdldF9y ZWxhdGlvbl9zdGF0c19ob29rX3R5cGUgZ2V0X3JlbGF0aW9uX3N0YXRzX2hvb2sgPSBOVUxM OwogZ2V0X2luZGV4X3N0YXRzX2hvb2tfdHlwZSBnZXRfaW5kZXhfc3RhdHNfaG9vayA9IE5V TEw7CiAKIHN0YXRpYyBkb3VibGUgZXFzZWxfaW50ZXJuYWwoUEdfRlVOQ1RJT05fQVJHUywg Ym9vbCBuZWdhdGUpOworc3RhdGljIGRvdWJsZSBzY2FsYXJhcnJheV9tY3ZfaGFzaF9tYXRj aChWYXJpYWJsZVN0YXREYXRhICp2YXJkYXRhLCBPaWQgb3BlcmF0b3IsIE9pZCBjb2xsYXRp b24sCisJCQkJCQkJCQkJIE5vZGUgKm90aGVyX29wLCBib29sIHZhcl9vbl9sZWZ0LCBEYXR1 bSAqZWxlbV92YWx1ZXMsCisJCQkJCQkJCQkJIGJvb2wgKmVsZW1fbnVsbHMsIGludCBudW1f ZWxlbXMsCisJCQkJCQkJCQkJIGJvb2wgdXNlT3IsIGJvb2wgaXNFcXVhbGl0eSwgYm9vbCBp c0luZXF1YWxpdHkpOworc3RhdGljIHVpbnQzMiBoYXNoX21jdl9pbihNQ1ZJbkhhc2hUYWJs ZV9oYXNoICp0YWIsIERhdHVtIGtleSk7CitzdGF0aWMgYm9vbCBtY3ZzX2luX2VxdWFsKE1D VkluSGFzaFRhYmxlX2hhc2ggKnRhYiwgRGF0dW0ga2V5MCwgRGF0dW0ga2V5MSk7CiBzdGF0 aWMgZG91YmxlIGVxam9pbnNlbF9pbm5lcihGbWdySW5mbyAqZXFwcm9jLCBPaWQgY29sbGF0 aW9uLAogCQkJCQkJCSAgT2lkIGhhc2hMZWZ0LCBPaWQgaGFzaFJpZ2h0LAogCQkJCQkJCSAg VmFyaWFibGVTdGF0RGF0YSAqdmFyZGF0YTEsIFZhcmlhYmxlU3RhdERhdGEgKnZhcmRhdGEy LApAQCAtMjg3LDYgKzMxOSwxOSBAQCBzdGF0aWMgZG91YmxlIGJ0Y29zdF9jb3JyZWxhdGlv bihJbmRleE9wdEluZm8gKmluZGV4LAogI2RlZmluZSBTSF9ERUNMQVJFCiAjaW5jbHVkZSAi bGliL3NpbXBsZWhhc2guaCIKIAorI2RlZmluZSBTSF9QUkVGSVgJCQkJTUNWSW5IYXNoVGFi bGUKKyNkZWZpbmUgU0hfRUxFTUVOVF9UWVBFCQkJTUNWSW5IYXNoRW50cnkKKyNkZWZpbmUg U0hfS0VZX1RZUEUJCQkJRGF0dW0KKyNkZWZpbmUgU0hfS0VZCQkJCQl2YWx1ZQorI2RlZmlu ZSBTSF9IQVNIX0tFWSh0YWIsa2V5KQloYXNoX21jdl9pbih0YWIsIGtleSkKKyNkZWZpbmUg U0hfRVFVQUwodGFiLGtleTAsa2V5MSkJbWN2c19pbl9lcXVhbCh0YWIsIGtleTAsIGtleTEp CisjZGVmaW5lIFNIX1NDT1BFCQkJCXN0YXRpYyBpbmxpbmUKKyNkZWZpbmUgU0hfU1RPUkVf SEFTSAorI2RlZmluZSBTSF9HRVRfSEFTSCh0YWIsZW50KQkoZW50KS0+aGFzaAorI2RlZmlu ZSBTSF9ERUZJTkUKKyNkZWZpbmUgU0hfREVDTEFSRQorI2luY2x1ZGUgImxpYi9zaW1wbGVo YXNoLmgiCisKIAogLyoKICAqCQllcXNlbAkJCS0gU2VsZWN0aXZpdHkgb2YgIj0iIGZvciBh bnkgZGF0YSB0eXBlcy4KQEAgLTIwMjUsNiArMjA3MCwzNSBAQCBzY2FsYXJhcnJheXNlbChQ bGFubmVySW5mbyAqcm9vdCwKIAkJCQkJCSAgZWxtbGVuLCBlbG1ieXZhbCwgZWxtYWxpZ24s CiAJCQkJCQkgICZlbGVtX3ZhbHVlcywgJmVsZW1fbnVsbHMsICZudW1fZWxlbXMpOwogCisJ CS8qCisJCSAqIFRyeSB0byBjYWxjdWxhdGUgc2VsZWN0aXZpdHkgYnkgaGFzaC1zZWFyY2gg TyhOKSBpbnN0ZWFkIG9mIE8oTl4yKQorCQkgKiBpbiBjYXNlIG9mIE1DViBtYXRjaGluZy4K KwkJICovCisJCWlmICgoaXNFcXVhbGl0eSB8fCBpc0luZXF1YWxpdHkpICYmICFpc19qb2lu X2NsYXVzZSkKKwkJeworCQkJVmFyaWFibGVTdGF0RGF0YSB2YXJkYXRhOworCQkJTm9kZQkg ICAqb3RoZXJfb3AgPSBOVUxMOworCQkJYm9vbAkJdmFyX29uX2xlZnQ7CisKKwkJCS8qCisJ CQkgKiBJZiBleHByZXNzaW9uIGlzIG5vdCB2YXJpYWJsZSA9IHNvbWV0aGluZyBvciBzb21l dGhpbmcgPQorCQkJICogdmFyaWFibGUsIHRoZW4gcHVudCBhbmQgcmV0dXJuIGEgZGVmYXVs dCBlc3RpbWF0ZS4KKwkJCSAqLworCQkJaWYgKGdldF9yZXN0cmljdGlvbl92YXJpYWJsZShy b290LCBjbGF1c2UtPmFyZ3MsIHZhclJlbGlkLAorCQkJCQkJCQkJCSAmdmFyZGF0YSwgJm90 aGVyX29wLCAmdmFyX29uX2xlZnQpKQorCQkJeworCQkJCXMxID0gc2NhbGFyYXJyYXlfbWN2 X2hhc2hfbWF0Y2goJnZhcmRhdGEsIG9wZXJhdG9yLCBjbGF1c2UtPmlucHV0Y29sbGlkLAor CQkJCQkJCQkJCQkJb3RoZXJfb3AsIHZhcl9vbl9sZWZ0LCBlbGVtX3ZhbHVlcywKKwkJCQkJ CQkJCQkJCWVsZW1fbnVsbHMsIG51bV9lbGVtcywKKwkJCQkJCQkJCQkJCXVzZU9yLCBpc0Vx dWFsaXR5LCBpc0luZXF1YWxpdHkpOworCisJCQkJUmVsZWFzZVZhcmlhYmxlU3RhdHModmFy ZGF0YSk7CisKKwkJCQlpZiAoczEgPj0gMC4wKQorCQkJCQlyZXR1cm4gczE7CisJCQl9CisJ CX0KKwogCQkvKgogCQkgKiBGb3IgZ2VuZXJpYyBvcGVyYXRvcnMsIHdlIGFzc3VtZSB0aGUg cHJvYmFiaWxpdHkgb2Ygc3VjY2VzcyBpcwogCQkgKiBpbmRlcGVuZGVudCBmb3IgZWFjaCBh cnJheSBlbGVtZW50LiAgQnV0IGZvciAiPSBBTlkiIG9yICI8PiBBTEwiLApAQCAtMjIxMCw2 ICsyMjg0LDMyMCBAQCBzY2FsYXJhcnJheXNlbChQbGFubmVySW5mbyAqcm9vdCwKIAlyZXR1 cm4gczE7CiB9CiAKKy8qCisgKiBFc3RpbWF0ZSBzZWxlY3Rpdml0eSBvZiBhIFNjYWxhckFy cmF5T3BFeHByIHVzaW5nIE1DViBzdGF0aXN0aWNzIGFuZCwKKyAqIHdoZW4gYmVuZWZpY2lh bCwgYSBoYXNoIHRhYmxlIGZvciBlZmZpY2llbnQgbWF0Y2hpbmcuCisgKgorICogVGhlIGZ1 bmN0aW9uIGV2YWx1YXRlcyBzZWxlY3Rpdml0eSBieSBjb21wYXJpbmcgZWFjaCBlbGVtZW50 IG9mIHRoZQorICogSU4tbGlzdCBhZ2FpbnN0IHRoZSBjb2x1bW4ncyBtb3N0LWNvbW1vbiB2 YWx1ZXMgKE1DVnMpLgorICoKKyAqIElucHV0czoKKyAqCXZhcmRhdGE6IHN0YXRpc3RpY3Mg YW5kIG1ldGFkYXRhIGZvciB0aGUgdmFyaWFibGUgYmVpbmcgZXN0aW1hdGVkCisgKglvcGVy YXRvcjogZXF1YWxpdHkgb3IgaW5lcXVhbGl0eSBvcGVyYXRvciB0byBhcHBseQorICoJY29s bGF0aW9uOiBPSUQgb2YgY29sbGF0aW9uIHRvIHVzZQorICoJb3RoZXJfb3A6IGV4cHJlc3Np b24gZm9yIHRoZSBub24tdmFyaWFibGUgc2lkZSBvZiB0aGUgY29tcGFyaXNvbgorICoJdmFy X29uX2xlZnQ6IHRydWUgaWYgdGhlIHZhcmlhYmxlIGlzIG9uIHRoZSBsZWZ0IHNpZGUgb2Yg dGhlIG9wZXJhdG9yCisgKgllbGVtX3ZhbHVlczogYXJyYXkgb2YgSU4tbGlzdCBlbGVtZW50 IHZhbHVlcworICoJZWxlbV9udWxsczogYXJyYXkgaW5kaWNhdGluZyB3aGljaCBJTi1saXN0 IGVsZW1lbnRzIGFyZSBOVUxMCisgKgludW1fZWxlbXM6IG51bWJlciBvZiBJTi1saXN0IGVs ZW1lbnRzCisgKgl1c2VPcjogdHJ1ZSBpZiBlbGVtZW50cyBhcmUgY29tYmluZWQgdXNpbmcg T1Igc2VtYW50aWNzLCBmYWxzZSBmb3IgQU5ECisgKglpc0VxdWFsaXR5OiB0cnVlIGlmIHRo ZSBvcGVyYXRvciBpcyBlcXVhbGl0eQorICoJaXNJbmVxdWFsaXR5OiB0cnVlIGlmIHRoZSBv cGVyYXRvciBpcyBpbmVxdWFsaXR5CisgKgorICogUmVzdWx0OgorICoJUmV0dXJucyBhIHNl bGVjdGl2aXR5IGVzdGltYXRlIGluIHRoZSByYW5nZSBbMC4wLCAxLjBdLCBvciAtMS4wIGlm IHRoZQorICoJc2VsZWN0aXZpdHkgY2Fubm90IGJlIHJlbGlhYmx5IGVzdGltYXRlZCBieSB0 aGlzIGZ1bmN0aW9uLgorICovCitzdGF0aWMgZG91YmxlCitzY2FsYXJhcnJheV9tY3ZfaGFz aF9tYXRjaChWYXJpYWJsZVN0YXREYXRhICp2YXJkYXRhLCBPaWQgb3BlcmF0b3IsIE9pZCBj b2xsYXRpb24sCisJCQkJCQkgICBOb2RlICpvdGhlcl9vcCwgYm9vbCB2YXJfb25fbGVmdCwg RGF0dW0gKmVsZW1fdmFsdWVzLAorCQkJCQkJICAgYm9vbCAqZWxlbV9udWxscywgaW50IG51 bV9lbGVtcywKKwkJCQkJCSAgIGJvb2wgdXNlT3IsIGJvb2wgaXNFcXVhbGl0eSwgYm9vbCBp c0luZXF1YWxpdHkpCit7CisJRm9ybV9wZ19zdGF0aXN0aWMgc3RhdHM7CisJQXR0U3RhdHNT bG90IHNzbG90OworCUZtZ3JJbmZvCWVxcHJvYzsKKwlkb3VibGUJCXNlbGVjID0gLTEuMCwK KwkJCQlzMWRpc2pvaW50LAorCQkJCW51bGxmcmFjID0gMC4wOworCU9pZAkJCWhhc2hMZWZ0 ID0gSW52YWxpZE9pZCwKKwkJCQloYXNoUmlnaHQgPSBJbnZhbGlkT2lkLAorCQkJCW9wZnVu Y29pZDsKKwlib29sCQloYXZlX21jdnMgPSBmYWxzZTsKKworCUFzc2VydChpc0VxdWFsaXR5 IHx8IGlzSW5lcXVhbGl0eSk7CisKKwkvKgorCSAqIElmIHdlIG1hdGNoZWQgdGhlIHZhciB0 byBhIHVuaXF1ZSBpbmRleCwgRElTVElOQ1Qgb3IgR1JPVVAtQlkgY2xhdXNlLAorCSAqIGFz c3VtZSB0aGVyZSBpcyBleGFjdGx5IG9uZSBtYXRjaCByZWdhcmRsZXNzIG9mIGFueXRoaW5n IGVsc2UuICAoVGhpcworCSAqIGlzIHNsaWdodGx5IGJvZ3VzLCBzaW5jZSB0aGUgaW5kZXgg b3IgY2xhdXNlJ3MgZXF1YWxpdHkgb3BlcmF0b3IgbWlnaHQKKwkgKiBiZSBkaWZmZXJlbnQg ZnJvbSBvdXJzLCBidXQgaXQncyBtdWNoIG1vcmUgbGlrZWx5IHRvIGJlIHJpZ2h0IHRoYW4K KwkgKiBpZ25vcmluZyB0aGUgaW5mb3JtYXRpb24uKQorCSAqLworCWlmICh2YXJkYXRhLT5p c3VuaXF1ZSAmJiB2YXJkYXRhLT5yZWwgJiYgdmFyZGF0YS0+cmVsLT50dXBsZXMgPj0gMS4w KQorCQlyZXR1cm4gLTEuMDsKKworCS8qCisJICogV2hlbiBhc2tlZCBhYm91dCA8Piwgd2Ug ZG8gdGhlIGVzdGltYXRpb24gdXNpbmcgdGhlIGNvcnJlc3BvbmRpbmcgPQorCSAqIG9wZXJh dG9yLgorCSAqLworCWlmIChpc0luZXF1YWxpdHkpCisJeworCQlvcGVyYXRvciA9IGdldF9u ZWdhdG9yKG9wZXJhdG9yKTsKKwkJaWYgKCFPaWRJc1ZhbGlkKG9wZXJhdG9yKSkKKwkJCXJl dHVybiAtMS4wOworCX0KKworCW9wZnVuY29pZCA9IGdldF9vcGNvZGUob3BlcmF0b3IpOwor CisJbWVtc2V0KCZzc2xvdCwgMCwgc2l6ZW9mKHNzbG90KSk7CisKKwlpZiAoSGVhcFR1cGxl SXNWYWxpZCh2YXJkYXRhLT5zdGF0c1R1cGxlKSkKKwl7CisJCWlmIChzdGF0aXN0aWNfcHJv Y19zZWN1cml0eV9jaGVjayh2YXJkYXRhLCBvcGZ1bmNvaWQpKQorCQkJaGF2ZV9tY3ZzID0g Z2V0X2F0dHN0YXRzc2xvdCgmc3Nsb3QsIHZhcmRhdGEtPnN0YXRzVHVwbGUsCisJCQkJCQkJ CQkJIFNUQVRJU1RJQ19LSU5EX01DViwgSW52YWxpZE9pZCwKKwkJCQkJCQkJCQkgQVRUU1RB VFNTTE9UX1ZBTFVFUyB8IEFUVFNUQVRTU0xPVF9OVU1CRVJTKTsKKwl9CisKKwlpZiAoaGF2 ZV9tY3ZzKQorCXsKKwkJZm1ncl9pbmZvKG9wZnVuY29pZCwgJmVxcHJvYyk7CisKKwkJLyoK KwkJICogSWYgdGhlIGNvbWJpbmVkIHNpemUgb2YgdGhlIE1DViBsaXN0IGFuZCB0aGUgSU4t bGlzdCBpcyBsYXJnZQorCQkgKiBlbm91Z2ggdG8ganVzdGlmeSBoYXNoaW5nLCBhdHRlbXB0 IHRvIGxvb2sgdXAgaGFzaCBmdW5jdGlvbnMgZm9yCisJCSAqIHRoZSBvcGVyYXRvci4KKwkJ ICovCisJCWlmIChzc2xvdC5udmFsdWVzICsgbnVtX2VsZW1zID49IFNDQUxBUkFSUkFZX01D Vl9IQVNIX1RIUkVTSE9MRCkKKwkJCSh2b2lkKSBnZXRfb3BfaGFzaF9mdW5jdGlvbnMob3Bl cmF0b3IsICZoYXNoTGVmdCwgJmhhc2hSaWdodCk7CisJfQorCisJaWYgKGhhdmVfbWN2cyAm JiBPaWRJc1ZhbGlkKGhhc2hMZWZ0KSAmJiBPaWRJc1ZhbGlkKGhhc2hSaWdodCkpCisJewor CQkvKiBVc2UgYSBoYXNoIHRhYmxlIHRvIHNwZWVkIHVwIHRoZSBtYXRjaGluZyAqLworCQlM T0NBTF9GQ0lORk8oZmNpbmZvLCAyKTsKKwkJTE9DQUxfRkNJTkZPKGhhc2hfZmNpbmZvLCAx KTsKKwkJTUNWSW5IYXNoVGFibGVfaGFzaCAqaGFzaFRhYmxlOworCQlGbWdySW5mbwloYXNo X3Byb2M7CisJCU1DVkluSGFzaENvbnRleHQgaGFzaENvbnRleHQ7CisJCWRvdWJsZQkJc3Vt YWxsY29tbW9uID0gMC4wLAorCQkJCQlyZW1haW5pbmdfc2VsZWMgPSAwLjA7CisJCWJvb2wJ CWlzZGVmYXVsdDsKKwkJZG91YmxlCQlvdGhlcmRpc3RpbmN0OworCisJCS8qIEdyYWIgdGhl IG51bGxmcmFjIGZvciB1c2UgYmVsb3cuICovCisJCXN0YXRzID0gKEZvcm1fcGdfc3RhdGlz dGljKSBHRVRTVFJVQ1QodmFyZGF0YS0+c3RhdHNUdXBsZSk7CisJCW51bGxmcmFjID0gc3Rh dHMtPnN0YW51bGxmcmFjOworCisJCXNlbGVjID0gczFkaXNqb2ludCA9ICh1c2VPciA/IDAu MCA6IDEuMCk7CisKKwkJSW5pdEZ1bmN0aW9uQ2FsbEluZm9EYXRhKCpmY2luZm8sICZlcXBy b2MsIDIsIGNvbGxhdGlvbiwKKwkJCQkJCQkJIE5VTEwsIE5VTEwpOworCQlmY2luZm8tPmFy Z3NbMF0uaXNudWxsID0gZmFsc2U7CisJCWZjaW5mby0+YXJnc1sxXS5pc251bGwgPSBmYWxz ZTsKKworCQkvKgorCQkgKiBCdWlsZCB0aGUgaGFzaCB0YWJsZSB1c2luZyB0aGUgTUNWIGFy cmF5IGFzIGtleXMsIHJhdGhlciB0aGFuIHRoZQorCQkgKiBJTi1saXN0IGVsZW1lbnRzLgor CQkgKgorCQkgKiBUaGUgTUNWIGxpc3QgaXMgZ3VhcmFudGVlZCB0byBjb250YWluIGRpc3Rp bmN0IHZhbHVlcy4gSGFzaGluZyB0aGUKKwkJICogTUNWcyBhbGxvd3MgdXMgdG8gZWZmaWNp ZW50bHkgaWRlbnRpZnkgd2hldGhlciBhIGdpdmVuIElOLWxpc3QKKwkJICogZWxlbWVudCBt YXRjaGVzIGEgbW9zdC1jb21tb24gdmFsdWUsIHdoaWNoIGlzIGV4YWN0bHkgd2hhdCBpcwor CQkgKiBuZWVkZWQgZm9yIGFjY3VyYXRlIHNlbGVjdGl2aXR5IGVzdGltYXRpb24uCisJCSAq LworCQlmbWdyX2luZm8oaGFzaExlZnQsICZoYXNoX3Byb2MpOworCQlJbml0RnVuY3Rpb25D YWxsSW5mb0RhdGEoKmhhc2hfZmNpbmZvLCAmaGFzaF9wcm9jLCAxLCBjb2xsYXRpb24sCisJ CQkJCQkJCSBOVUxMLCBOVUxMKTsKKwkJaGFzaF9mY2luZm8tPmFyZ3NbMF0uaXNudWxsID0g ZmFsc2U7CisKKwkJaGFzaENvbnRleHQuZXF1YWxfZmNpbmZvID0gZmNpbmZvOworCQloYXNo Q29udGV4dC5oYXNoX2ZjaW5mbyA9IGhhc2hfZmNpbmZvOworCQloYXNoQ29udGV4dC5pbnNl cnRfbW9kZSA9IHRydWU7CisKKwkJZ2V0X3R5cGxlbmJ5dmFsKHNzbG90LnZhbHVldHlwZSwK KwkJCQkJCSZoYXNoQ29udGV4dC5oYXNoX3R5cGxlbiwKKwkJCQkJCSZoYXNoQ29udGV4dC5o YXNoX3R5cGJ5dmFsKTsKKworCQloYXNoVGFibGUgPSBNQ1ZJbkhhc2hUYWJsZV9jcmVhdGUo Q3VycmVudE1lbW9yeUNvbnRleHQsCisJCQkJCQkJCQkJICBzc2xvdC5udmFsdWVzLAorCQkJ CQkJCQkJCSAgJmhhc2hDb250ZXh0KTsKKworCQlmb3IgKGludCBpID0gMDsgaSA8IHNzbG90 Lm52YWx1ZXM7IGkrKykKKwkJeworCQkJYm9vbAkJZm91bmQgPSBmYWxzZTsKKwkJCU1DVklu SGFzaEVudHJ5ICplbnRyeTsKKworCQkJZW50cnkgPSBNQ1ZJbkhhc2hUYWJsZV9pbnNlcnQo aGFzaFRhYmxlLCBzc2xvdC52YWx1ZXNbaV0sICZmb3VuZCk7CisKKwkJCS8qCisJCQkgKiBN Q1ZIYXNoVGFibGVfaW5zZXJ0IHdpbGwgb25seSByZXBvcnQgImZvdW5kIiBpZiB0aGUgbmV3 IHZhbHVlCisJCQkgKiBpcyBlcXVhbCB0byBzb21lIHByZXZpb3VzIG9uZSBwZXIgZGF0dW1f aW1hZ2VfZXEoKS4gIFRoYXQKKwkJCSAqIHByb2JhYmx5IHNob3VsZG4ndCBoYXBwZW4sIHNp bmNlIHdlJ3JlIG5vdCBleHBlY3RpbmcgZHVwbGljYXRlcworCQkJICogaW4gdGhlIE1DViBs aXN0LiAgSWYgd2UgZG8gZmluZCBhIGR1cCwganVzdCBpZ25vcmUgaXQsIGxlYXZpbmcKKwkJ CSAqIHRoZSBoYXNoIGVudHJ5J3MgaW5kZXggcG9pbnRpbmcgYXQgdGhlIGZpcnN0IG9jY3Vy cmVuY2UuICBUaGF0CisJCQkgKiBtYXRjaGVzIHRoZSBiZWhhdmlvciB0aGF0IHRoZSBub24t aGFzaGVkIGNvZGUgcGF0aCB3b3VsZCBoYXZlLgorCQkJICovCisJCQlpZiAobGlrZWx5KCFm b3VuZCkpCisJCQkJZW50cnktPmluZGV4ID0gaTsKKworCQkJc3VtYWxsY29tbW9uICs9IHNz bG90Lm51bWJlcnNbaV07CisJCX0KKworCQkvKgorCQkgKiBQcmVwYXJlIHRvIHByb2JlIHRo ZSBoYXNoIHRhYmxlLiAgSWYgdGhlIHByb2JlIHZhbHVlcyBhcmUgb2YgYQorCQkgKiBkaWZm ZXJlbnQgZGF0YSB0eXBlLCB0aGVuIHdlIG5lZWQgdG8gY2hhbmdlIGhhc2ggZnVuY3Rpb25z LiAgKFRoaXMKKwkJICogY29kZSByZWxpZXMgb24gdGhlIGFzc3VtcHRpb24gdGhhdCBzaW5j ZSB3ZSBkZWZpbmVkIFNIX1NUT1JFX0hBU0gsCisJCSAqIHNpbXBsZWhhc2guaCB3aWxsIG5l dmVyIG5lZWQgdG8gY29tcHV0ZSBoYXNoIHZhbHVlcyBmb3IgZXhpc3RpbmcKKwkJICogaGFz aCB0YWJsZSBlbnRyaWVzLikKKwkJICovCisJCWhhc2hDb250ZXh0Lmluc2VydF9tb2RlID0g ZmFsc2U7CisJCWlmIChoYXNoTGVmdCAhPSBoYXNoUmlnaHQpCisJCXsKKworCQkJZm1ncl9p bmZvKGhhc2hSaWdodCwgJmhhc2hfcHJvYyk7CisJCQkvKiBSZXNldHRpbmcgaGFzaF9mY2lu Zm8gaXMgcHJvYmFibHkgdW5uZWNlc3NhcnksIGJ1dCBiZSBzYWZlICovCisJCQlJbml0RnVu Y3Rpb25DYWxsSW5mb0RhdGEoKmhhc2hfZmNpbmZvLCAmaGFzaF9wcm9jLCAxLCBjb2xsYXRp b24sCisJCQkJCQkJCQkgTlVMTCwgTlVMTCk7CisJCQloYXNoX2ZjaW5mby0+YXJnc1swXS5p c251bGwgPSBmYWxzZTsKKwkJfQorCisJCS8qCisJCSAqIENvbXBhcmlzb24gaXMgYWdhaW5z dCBhIGNvbnN0YW50IHRoYXQgaXMgbmVpdGhlciBOVUxMIG5vciBhbnkgb2YKKwkJICogdGhl IGNvbW1vbiB2YWx1ZXMuICBJdHMgc2VsZWN0aXZpdHkgY2Fubm90IGJlIG1vcmUgdGhhbiB0 aGlzOgorCQkgKi8KKwkJcmVtYWluaW5nX3NlbGVjID0gMS4wIC0gc3VtYWxsY29tbW9uIC0g bnVsbGZyYWM7CisJCUNMQU1QX1BST0JBQklMSVRZKHJlbWFpbmluZ19zZWxlYyk7CisKKwkJ LyoKKwkJICogYW5kIGluIGZhY3QgaXQncyBwcm9iYWJseSBhIGdvb2QgZGVhbCBsZXNzLiBX ZSBhcHByb3hpbWF0ZSB0aGF0IGFsbAorCQkgKiB0aGUgbm90LWNvbW1vbiB2YWx1ZXMgc2hh cmUgdGhpcyByZW1haW5pbmcgZnJhY3Rpb24gZXF1YWxseSwgc28gd2UKKwkJICogZGl2aWRl IGJ5IHRoZSBudW1iZXIgb2Ygb3RoZXIgZGlzdGluY3QgdmFsdWVzLgorCQkgKi8KKwkJb3Ro ZXJkaXN0aW5jdCA9IGdldF92YXJpYWJsZV9udW1kaXN0aW5jdCh2YXJkYXRhLCAmaXNkZWZh dWx0KSAtIHNzbG90Lm5udW1iZXJzOworCQlpZiAob3RoZXJkaXN0aW5jdCA+IDEpCisJCQly ZW1haW5pbmdfc2VsZWMgLz0gb3RoZXJkaXN0aW5jdDsKKworCQkvKgorCQkgKiBBbm90aGVy IGNyb3NzLWNoZWNrOiBzZWxlY3Rpdml0eSBzaG91bGRuJ3QgYmUgZXN0aW1hdGVkIGFzIG1v cmUKKwkJICogdGhhbiB0aGUgbGVhc3QgY29tbW9uICJtb3N0IGNvbW1vbiB2YWx1ZSIuCisJ CSAqLworCQlpZiAoc3Nsb3Qubm51bWJlcnMgPiAwICYmIHJlbWFpbmluZ19zZWxlYyA+IHNz bG90Lm51bWJlcnNbc3Nsb3Qubm51bWJlcnMgLSAxXSkKKwkJCXJlbWFpbmluZ19zZWxlYyA9 IHNzbG90Lm51bWJlcnNbc3Nsb3Qubm51bWJlcnMgLSAxXTsKKworCQkvKiBFdmFsdWF0ZSBz ZWxlY3Rpdml0eSBjb250cmlidXRpb24gb2YgZWFjaCBJTi1saXN0IGVsZW1lbnQuICovCisJ CWZvciAoaW50IGkgPSAwOyBpIDwgbnVtX2VsZW1zOyBpKyspCisJCXsKKwkJCU1DVkluSGFz aEVudHJ5ICplbnRyeTsKKwkJCVNlbGVjdGl2aXR5IHMxOworCisJCQkvKgorCQkJICogSWYg dGhlIGNvbnN0YW50IGlzIE5VTEwsIGFzc3VtZSBvcGVyYXRvciBpcyBzdHJpY3QgYW5kIHJl dHVybgorCQkJICogczEgemVyby4gKEl0J3MgemVybyBldmVuIGZvciBhIG5lZ2F0b3Igb3Au KQorCQkJICovCisJCQlpZiAoZWxlbV9udWxsc1tpXSkKKwkJCQljb250aW51ZTsKKworCQkJ aWYgKElzQShvdGhlcl9vcCwgQ29uc3QpKQorCQkJeworCQkJCWVudHJ5ID0gTUNWSW5IYXNo VGFibGVfbG9va3VwKGhhc2hUYWJsZSwgZWxlbV92YWx1ZXNbaV0pOworCisJCQkJaWYgKGVu dHJ5ICE9IE5VTEwpCisJCQkJeworCQkJCQkvKgorCQkJCQkgKiBBcyBpbiB0aGUgb3RoZXIg Y29kZSBwYXRoLCBza2lwIGFscmVhZHktbWF0Y2hlZCBoYXNoCisJCQkJCSAqIGVudHJpZXMK KwkJCQkJICovCisJCQkJCXMxID0gc3Nsb3QubnVtYmVyc1tlbnRyeS0+aW5kZXhdOworCQkJ CX0KKwkJCQllbHNlCisJCQkJCXMxID0gcmVtYWluaW5nX3NlbGVjOworCisJCQkJaWYgKGlz SW5lcXVhbGl0eSkKKwkJCQkJczEgPSAxLjAgLSBzMSAtIG51bGxmcmFjOworCQkJfQorCQkJ ZWxzZQorCQkJCXMxID0gdmFyX2VxX25vbl9jb25zdCh2YXJkYXRhLCBvcGVyYXRvciwgY29s bGF0aW9uLCBvdGhlcl9vcCwKKwkJCQkJCQkJCSAgdmFyX29uX2xlZnQsIGlzSW5lcXVhbGl0 eSk7CisKKwkJCUNMQU1QX1BST0JBQklMSVRZKHMxKTsKKworCQkJaWYgKHVzZU9yKQorCQkJ eworCQkJCXNlbGVjID0gc2VsZWMgKyBzMSAtIHNlbGVjICogczE7CisJCQkJaWYgKGlzRXF1 YWxpdHkpCisJCQkJCXMxZGlzam9pbnQgKz0gczE7CisJCQl9CisJCQllbHNlCisJCQl7CisJ CQkJc2VsZWMgPSBzZWxlYyAqIHMxOworCQkJCWlmIChpc0luZXF1YWxpdHkpCisJCQkJCXMx ZGlzam9pbnQgKz0gczEgLSAxLjA7CisJCQl9CisJCX0KKworCQlNQ1ZJbkhhc2hUYWJsZV9k ZXN0cm95KGhhc2hUYWJsZSk7CisKKwkJLyogYWNjZXB0IGRpc2pvaW50LXByb2JhYmlsaXR5 IGVzdGltYXRlIGlmIGluIHJhbmdlICovCisJCWlmICgodXNlT3IgPyBpc0VxdWFsaXR5IDog aXNJbmVxdWFsaXR5KSAmJgorCQkJczFkaXNqb2ludCA+PSAwLjAgJiYgczFkaXNqb2ludCA8 PSAxLjApCisJCQlzZWxlYyA9IHMxZGlzam9pbnQ7CisKKwkJQ0xBTVBfUFJPQkFCSUxJVFko c2VsZWMpOworCX0KKworCWZyZWVfYXR0c3RhdHNzbG90KCZzc2xvdCk7CisKKwlyZXR1cm4g c2VsZWM7Cit9CisKKy8qCisgKiBTdXBwb3J0IGZ1bmN0aW9ucyBmb3IgdGhlIGhhc2ggdGFi bGVzIHVzZWQgYnkgZXFqb2luc2VsX2ZpbmRfbWF0Y2hlcworICovCitzdGF0aWMgdWludDMy CitoYXNoX21jdl9pbihNQ1ZJbkhhc2hUYWJsZV9oYXNoICp0YWIsIERhdHVtIGtleSkKK3sK KwlNQ1ZJbkhhc2hDb250ZXh0ICpjb250ZXh0ID0gKE1DVkluSGFzaENvbnRleHQgKikgdGFi LT5wcml2YXRlX2RhdGE7CisJRnVuY3Rpb25DYWxsSW5mbyBmY2luZm8gPSBjb250ZXh0LT5o YXNoX2ZjaW5mbzsKKwlEYXR1bQkJZnJlc3VsdDsKKworCWZjaW5mby0+YXJnc1swXS52YWx1 ZSA9IGtleTsKKwlmY2luZm8tPmlzbnVsbCA9IGZhbHNlOworCWZyZXN1bHQgPSBGdW5jdGlv bkNhbGxJbnZva2UoZmNpbmZvKTsKKwlBc3NlcnQoIWZjaW5mby0+aXNudWxsKTsKKwlyZXR1 cm4gRGF0dW1HZXRVSW50MzIoZnJlc3VsdCk7Cit9CisKK3N0YXRpYyBib29sCittY3ZzX2lu X2VxdWFsKE1DVkluSGFzaFRhYmxlX2hhc2ggKnRhYiwgRGF0dW0ga2V5MCwgRGF0dW0ga2V5 MSkKK3sKKwlNQ1ZJbkhhc2hDb250ZXh0ICpjb250ZXh0ID0gKE1DVkluSGFzaENvbnRleHQg KikgdGFiLT5wcml2YXRlX2RhdGE7CisKKwlpZiAoY29udGV4dC0+aW5zZXJ0X21vZGUpCisJ eworCQkvKgorCQkgKiBEdXJpbmcgdGhlIGluc2VydGlvbiBzdGVwLCBhbnkgY29tcGFyaXNv bnMgd2lsbCBiZSBiZXR3ZWVuIHR3bworCQkgKiBEYXR1bXMgb2YgdGhlIGhhc2ggdGFibGUn cyBkYXRhIHR5cGUsIHNvIGlmIHRoZSBnaXZlbiBvcGVyYXRvciBpcworCQkgKiBjcm9zcy10 eXBlIGl0IHdpbGwgYmUgdGhlIHdyb25nIHRoaW5nIHRvIHVzZS4gIEZvcnR1bmF0ZWx5LCB3 ZSBjYW4KKwkJICogdXNlIGRhdHVtX2ltYWdlX2VxIGluc3RlYWQuICBUaGUgTUNWIHZhbHVl cyBzaG91bGQgYWxsIGJlIGRpc3RpbmN0CisJCSAqIGFueXdheSwgc28gaXQncyBtb3N0bHkg cHJvLWZvcm1hIHRvIGNvbXBhcmUgdGhlbSBhdCBhbGwuCisJCSAqLworCQlyZXR1cm4gZGF0 dW1faW1hZ2VfZXEoa2V5MCwga2V5MSwKKwkJCQkJCQkgIGNvbnRleHQtPmhhc2hfdHlwYnl2 YWwsIGNvbnRleHQtPmhhc2hfdHlwbGVuKTsKKwl9CisJZWxzZQorCXsKKwkJRnVuY3Rpb25D YWxsSW5mbyBmY2luZm8gPSBjb250ZXh0LT5lcXVhbF9mY2luZm87CisJCURhdHVtCQlmcmVz dWx0OworCisJCWZjaW5mby0+YXJnc1swXS52YWx1ZSA9IGtleTA7CisJCWZjaW5mby0+YXJn c1sxXS52YWx1ZSA9IGtleTE7CisJCWZjaW5mby0+aXNudWxsID0gZmFsc2U7CisJCWZyZXN1 bHQgPSBGdW5jdGlvbkNhbGxJbnZva2UoZmNpbmZvKTsKKwkJcmV0dXJuICghZmNpbmZvLT5p c251bGwgJiYgRGF0dW1HZXRCb29sKGZyZXN1bHQpKTsKKwl9Cit9CisKIC8qCiAgKiBFc3Rp bWF0ZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gdGhlIGFycmF5IHlpZWxkZWQgYnkgYW4gZXhw cmVzc2lvbi4KICAqCmRpZmYgLS1naXQgYS9zcmMvdG9vbHMvcGdpbmRlbnQvdHlwZWRlZnMu bGlzdCBiL3NyYy90b29scy9wZ2luZGVudC90eXBlZGVmcy5saXN0CmluZGV4IGNlYjNmYzVk OTgwLi4xN2Y1Y2M5NDc2YiAxMDA2NDQKLS0tIGEvc3JjL3Rvb2xzL3BnaW5kZW50L3R5cGVk ZWZzLmxpc3QKKysrIGIvc3JjL3Rvb2xzL3BnaW5kZW50L3R5cGVkZWZzLmxpc3QKQEAgLTE2 NjYsNiArMTY2Niw5IEBAIE1CdWYKIE1DVkhhc2hDb250ZXh0CiBNQ1ZIYXNoRW50cnkKIE1D Vkhhc2hUYWJsZV9oYXNoCitNQ1ZJbkhhc2hDb250ZXh0CitNQ1ZJbkhhc2hFbnRyeQorTUNW SW5IYXNoVGFibGVfaGFzaAogTUNWSXRlbQogTUNWTGlzdAogTUVNT1JZX0JBU0lDX0lORk9S TUFUSU9OCi0tIAoyLjM0LjEKCg== --------------xmkzAvEO1Yaj0ARXCVW6G3KF--