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 1weWbg-004qgm-1J for pgsql-hackers@arkaria.postgresql.org; Tue, 30 Jun 2026 11:26:24 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1weWbf-007s6s-0m for pgsql-hackers@arkaria.postgresql.org; Tue, 30 Jun 2026 11:26:23 +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 1weWbe-007s6k-2s for pgsql-hackers@lists.postgresql.org; Tue, 30 Jun 2026 11:26:22 +0000 Received: from mail-qk1-x731.google.com ([2607:f8b0:4864:20::731]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1weWbc-00000000zq5-29RS for pgsql-hackers@lists.postgresql.org; Tue, 30 Jun 2026 11:26:22 +0000 Received: by mail-qk1-x731.google.com with SMTP id af79cd13be357-92e65e18969so56167085a.1 for ; Tue, 30 Jun 2026 04:26:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1782818779; cv=none; d=google.com; s=arc-20260327; b=ijaMl8OETnxHERXILlryTZOpSN77dO5jciynBxbfxnF5nJOxRQ6O/5JPlTwzPL66LH 630UYhQnB54hgS1tLXEvOsEA8I8Ty5qWOBmEciu0kE3ZDLNvzCVHZAnvFg7I3by6xLlZ 1/NTuB13rkurcRJ/xgYReQZliqNYaec1akCpD8VMwOo2FiKiDrdf2Ox8Usim8k0C6q1v zpPMwWheVxkH/sRjso98YUHV7feynIfkax1mHUwqJPvBdBVW/phlH97lKQDDyQYM9YQU DZkHhlpl86jQocVEMmuJ0+4K4b/hyw1h/+PrqBpZPRAH+Fm9W3T9xO2fPvrF0tO8/MCJ iTAA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:from:mime-version:dkim-signature; bh=+SqoUJW4t8BlPRP62s47s8JXMM9bN8rR8BWRyMkXpYE=; fh=Haf/HxBthOYmv5veEQr3LkM/6waLjAEsR9a8Tb0hV00=; b=I3y4fSp7E/SjLCEw6HhJjeP7i4yHkfNU66SGqijs5cJMcKhuDbFn06tP3CgDQB/IG5 y6UJO8JPN37ttqv7hkf757OW4qUeibAnMfH0cT6g6E+rn6QrgSIyGB6MiR96o9dcTTB5 GTSBPp/ZJYRiQGfI1pK/0UangTcFWTDo2y2ZBYhoa/6Tr9Qk+KlsfridoYY5vfV7BY9O ao9U2gqNo3HP8Qh3C5jGDn9LhAn8m66CWnqZz0iRxDBprmfv3+feaVKdWIlEZ4OsIJOA fu0QGGho8c2u0QAmf5CKa7lSMQ4H3mYBFEL7AhvjZ0yPJAVSZRKOv5NTjKlaHedZKuEG WM8A==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1782818779; x=1783423579; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=+SqoUJW4t8BlPRP62s47s8JXMM9bN8rR8BWRyMkXpYE=; b=curU94RdT4poxU4LwGkHt11uWSGcg5isBPY+yYVUxzboRLA/FBV/Atfxvx8g9QfJ2H H+DAlu5/70g29NQeuBmT0hUeB8V1IaeYoNEn/rDB14XvTlg11xZygki5tiyz/GTgN+rH 448EiaipW0AFMaAMIHrOpJ5QL1vt1JvRkRv/SW0a7MVrURLdNE+LtuJtdJONyQ6JN7tM k8fr3Gl9jQCGuQnnTKoZfxhO/5CFhWk4fonatyOqadNXkiGv5YxAME1bgstl7obtWVpf RBUcEy4PZoxCOTK8RO8DRn8qatE6For/ROOyEZVBOL5NyLO8g8Z+Rp7vQPSvYs+E9iS6 G1aA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1782818779; x=1783423579; h=cc:to:subject:message-id:date:from:mime-version:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=+SqoUJW4t8BlPRP62s47s8JXMM9bN8rR8BWRyMkXpYE=; b=XmUBKAQOwpbfBe+b0WmtJGL4fCWHKPjhQpIRXcbAD1ksiICpJ/PcwZOc1Y8OlLuIgz cj0b9/DEMkm0ARqpfhdu3P94NhfbSFhg/8RbZ4tJqAya/+mJGIpezgD+XHpwCFujMkpR qGsbcg+rdRzeqIY6VG1eX8xoxQvPpmaXgcs/HJelrRIvD6qOzio1+oElKfSeNWE6jsaS 3aX94BVJpJ3k8wp6m4VWwF0spVCb1ltc1u6Sp+BQtSM75yt/qB53BncwanqXvJayR+vx AFaLHjauyiNYVClmNvPaSCDdLt/yrk2eQAzm3b7XVdTmwBB8IsYbl4Lb0R8PdKk2xaqV yJ+A== X-Gm-Message-State: AOJu0YzF+0ISzCH4l8q7M7O2kZaGRrCpmoffvKz9xMDl4kmrjWQHKkpb BsckwwlVSBcDcL5CnyhxVS08KPO5tKm1qLt5DkpAA/KY9K31qpiEaGPl5JhcYfot9J8EocxpsVk xclLP3k5HojTP6I8e4ICEDI0XMHGPafldTgq2cwxnrg== X-Gm-Gg: AfdE7cn7V+ZIsRMsluzdOryHtUdOQz5zzkv/6DpqgFiqUNMUcYoQSu4vtpfE22SswZs P1RWmn2EDC4uXL1gUIuNKm2xav56Vd/mVfaAPFeErQ9tqSN5rO5Sg5YFEf5+B2O+LWLZ84beXpI heJBDou2c0sNe1aSDWycTNUShqCRelXKmMoMLPaW8rMJcMuEc7W4UqixOR0l9KulV6ac7faaDss 4Q5W5w+E0ypMSaqs4+KKZOzXW+0WhAybveoTeDMMmMiTDVeM8Ipa5iFE51Ealx3yrDKmac= X-Received: by 2002:a05:620a:439a:b0:92e:3505:b24d with SMTP id af79cd13be357-92e6974d627mr146602885a.20.1782818777698; Tue, 30 Jun 2026 04:26:17 -0700 (PDT) MIME-Version: 1.0 From: prankware Date: Tue, 30 Jun 2026 14:26:05 +0300 X-Gm-Features: AVVi8CdQvxdrF2A24ToV55vJHCb_eensdHivtXw1tICTvDJL5ikbADlaB_DZ1PI Message-ID: Subject: COALESCE patch To: pgsql-hackers@lists.postgresql.org Cc: ilya.evdokimov@tantorlabs.com Content-Type: multipart/mixed; boundary="000000000000f1c10d065576d722" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000f1c10d065576d722 Content-Type: text/plain; charset="UTF-8" Hi everyone, The planner ignores column statistics when an equality has a COALESCE expression on one side. For a clause like COALESCE(a, b) = $1, or a join on COALESCE(t1.a, t1.b) = COALESCE(t2.c, t2.d), there are no statistics on the COALESCE node itself, so eqsel() and eqjoinsel() return the generic 0.005 estimate while the per-column stats for a, b, c and d sit unused. The only way around this today is an expression index or extended statistics on that exact expression, which doesn't scale across many different COALESCE clauses. estimate_hash_bucket_stats() has the same gap: a COALESCE hash key gets a default ndistinct and therefore a default bucket size. Since these expressions are common in joins and filters over nullable or fallback columns, the default estimate can be far enough off to flip the join order or join method. The idea is to estimate straight from the existing per-column stats, with no extra statistics object. COALESCE(arg_1, ..., arg_n) returns arg_i only when arg_1 .. arg_{i-1} are all NULL, so the chance of reaching branch i is the product of stanullfrac over the earlier branches. Selectivity of COALESCE(l_1..l_M) = COALESCE(r_1..r_N) is then the sum over branch pairs of P(reach l_i) * P(reach r_j) * sel(l_i = r_j), and each sel(l_i = r_j) is a recursive call back into eqsel()/eqjoinsel(). A non-COALESCE side is treated as a one-branch list, so scalar COALESCE(a, b) = const falls out of the same code, and the same decomposition feeds estimate_hash_bucket_stats(). If any branch is missing stats, the code bails and today's behavior is unchanged. A minimal example: CREATE TABLE t (a int, b int); INSERT INTO t SELECT CASE WHEN i % 5 < 2 THEN NULL ELSE i END, i FROM generate_series(1, 1000) i; ANALYZE t; EXPLAIN SELECT * FROM t WHERE COALESCE(a, b) = 42; After ANALYZE, a is NULL in 400 of the 1000 rows (stanullfrac 0.4, ndistinct 600) and b has no NULLs (stanullfrac 0, ndistinct 1000). COALESCE(a, b) is unique, so exactly one row matches. Each branch is weighted by the probability of reaching it, the product of stanullfrac over the branches before it: branch a: reach 1.0, sel(a = 42) = (1 - 0.4) / 600 = 0.001 branch b: reach 0.4, sel(b = 42) = (1 - 0.0) / 1000 = 0.001 selectivity = 1.0 * 0.001 + 0.4 * 0.001 = 0.0014 -> ~1 row out of 1000 The patch lands on ~1 row, matching reality. The 0.005 default (5 rows) is not derived from the table at all: it is the 1/DEFAULT_NUM_DISTINCT constant the planner falls back to with no statistics on the expression, so it stays 5 rows regardless of the null fraction or the ndistinct of a and b. Feedback is welcome. Regards, Egor Savelev, Tantor Labs LLC, https://tantorlabs.com/ --000000000000f1c10d065576d722 Content-Type: text/x-patch; charset="US-ASCII"; name="coalesce.patch" Content-Disposition: attachment; filename="coalesce.patch" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_mr0k90fg0 ZGlmZiAtLWdpdCBhL3NyYy9iYWNrZW5kL3V0aWxzL2FkdC9zZWxmdW5jcy5jIGIvc3JjL2JhY2tl bmQvdXRpbHMvYWR0L3NlbGZ1bmNzLmMKaW5kZXggZDZlZmQwNzA3M2EuLjNhNDc0OTVmZDBjIDEw MDY0NAotLS0gYS9zcmMvYmFja2VuZC91dGlscy9hZHQvc2VsZnVuY3MuYworKysgYi9zcmMvYmFj a2VuZC91dGlscy9hZHQvc2VsZnVuY3MuYwpAQCAtMzAyLDYgKzMwMiwyNzggQEAgZXFzZWwoUEdf RlVOQ1RJT05fQVJHUykKIAlQR19SRVRVUk5fRkxPQVQ4KChmbG9hdDgpIGVxc2VsX2ludGVybmFs KGZjaW5mbywgZmFsc2UpKTsKIH0KIAorLyoKKyAqIEV4dHJhY3QgdGhlIGVzdGltYWJsZSBicmFu Y2hlcyBvZiBhIENvYWxlc2NlRXhwci4gIFN0cmlwcyBSZWxhYmVsVHlwZSwKKyAqIHNraXBzIE5V TEwtY29uc3RhbnQgYnJhbmNoZXMsIGFuZCBzdG9wcyBhdCB0aGUgZmlyc3Qgbm9uLU5VTEwgQ29u c3QKKyAqIChzZXR0aW5nICp0ZXJtaW5hdGVzX3dpdGhfY29uc3QpLiAgUmV0dXJucyBmYWxzZSBp ZiB0aGUgZXhwcmVzc2lvbgorICogaXMgY29uc3RhbnQgb3Igbm8gYnJhbmNoZXMgcmVtYWluLgor ICovCitzdGF0aWMgYm9vbAorbWF0Y2hfY29hbGVzY2Vfam9pbl9zaWRlKE5vZGUgKnNpZGUsCisJ CQkJCQkgTGlzdCAqKnN0cmlwcGVkX2FyZ3MsCisJCQkJCQkgYm9vbCAqdGVybWluYXRlc193aXRo X2NvbnN0KQoreworCUNvYWxlc2NlRXhwciAqYzsKKwlMaXN0Q2VsbCAgICpsYzsKKwlMaXN0CSAg ICpyZXN1bHQgPSBOSUw7CisKKwkqdGVybWluYXRlc193aXRoX2NvbnN0ID0gZmFsc2U7CisJKnN0 cmlwcGVkX2FyZ3MgPSBOSUw7CisKKwlpZiAoc2lkZSA9PSBOVUxMIHx8ICFJc0Eoc2lkZSwgQ29h bGVzY2VFeHByKSkKKwkJcmV0dXJuIGZhbHNlOworCisJYyA9IChDb2FsZXNjZUV4cHIgKikgc2lk ZTsKKworCWlmIChsaXN0X2xlbmd0aChjLT5hcmdzKSA8IDIpCisJCXJldHVybiBmYWxzZTsKKwor CWZvcmVhY2gobGMsIGMtPmFyZ3MpCisJeworCQlOb2RlCSAgICphcmcgPSAoTm9kZSAqKSBsZmly c3QobGMpOworCisJCS8qIHN0cmlwIFJlbGFiZWxUeXBlICovCisJCXdoaWxlIChhcmcgJiYgSXNB KGFyZywgUmVsYWJlbFR5cGUpKQorCQkJYXJnID0gKE5vZGUgKikgKChSZWxhYmVsVHlwZSAqKSBh cmcpLT5hcmc7CisKKwkJLyogbGVhZGluZyBDb25zdCBtYWtlcyBDT0FMRVNDRSBpdHNlbGYgY29u c3RhbnQgKi8KKwkJaWYgKGFyZyA9PSBOVUxMIHx8IChsYyA9PSBsaXN0X2hlYWQoYy0+YXJncykg JiYgSXNBKGFyZywgQ29uc3QpKSkKKwkJeworCQkJbGlzdF9mcmVlKHJlc3VsdCk7CisJCQlyZXR1 cm4gZmFsc2U7CisJCX0KKworCQlpZiAoSXNBKGFyZywgQ29uc3QpKQorCQl7CisJCQlpZiAoKChD b25zdCAqKSBhcmcpLT5jb25zdHR5cGUgIT0gYy0+Y29hbGVzY2V0eXBlKQorCQkJeworCQkJCWxp c3RfZnJlZShyZXN1bHQpOworCQkJCXJldHVybiBmYWxzZTsKKwkJCX0KKworCQkJLyogTlVMTCBD b25zdCBpcyBza2lwcGVkICovCisJCQlpZiAoISgoQ29uc3QgKikgYXJnKS0+Y29uc3Rpc251bGwp CisJCQl7CisJCQkJcmVzdWx0ID0gbGFwcGVuZChyZXN1bHQsIGFyZyk7CisJCQkJKnRlcm1pbmF0 ZXNfd2l0aF9jb25zdCA9IHRydWU7CisJCQkJYnJlYWs7CisJCQl9CisJCX0KKwkJZWxzZQorCQl7 CisJCQlpZiAoZXhwclR5cGUoYXJnKSAhPSBjLT5jb2FsZXNjZXR5cGUpCisJCQl7CisJCQkJbGlz dF9mcmVlKHJlc3VsdCk7CisJCQkJcmV0dXJuIGZhbHNlOworCQkJfQorCQkJcmVzdWx0ID0gbGFw cGVuZChyZXN1bHQsIGFyZyk7CisJCX0KKwl9CisKKwlpZiAocmVzdWx0ID09IE5JTCkKKwkJcmV0 dXJuIGZhbHNlOworCisJKnN0cmlwcGVkX2FyZ3MgPSByZXN1bHQ7CisJcmV0dXJuIHRydWU7Cit9 CisKKy8qCisgKiBGaWxsIHByZWZpeF9wcm9ic1tpXSA9IFByb2Rfe2o8aX0gc3RhbnVsbGZyYWMo YXJnc1tqXSkgZm9yIGEgc3RyaXBwZWQKKyAqIENPQUxFU0NFIGFyZyBsaXN0LiAgUmV0dXJucyBm YWxzZSBpZiBhbnkgbm9uLUNvbnN0IGFyZyBsYWNrcyBzdGF0aXN0aWNzLgorICovCitzdGF0aWMg Ym9vbAorZ2V0X2NvYWxlc2NlX3ByZWZpeF9wcm9icyhQbGFubmVySW5mbyAqcm9vdCwgTGlzdCAq YXJncywgZG91YmxlICpwcmVmaXhfcHJvYnMpCit7CisJTGlzdENlbGwgICAqbGM7CisJaW50CQkJ aSA9IDA7CisJZG91YmxlCQlwcmVmaXggPSAxLjA7CisKKwlmb3JlYWNoKGxjLCBhcmdzKQorCXsK KwkJTm9kZQkgICAqYXJnID0gKE5vZGUgKikgbGZpcnN0KGxjKTsKKworCQlwcmVmaXhfcHJvYnNb aSsrXSA9IHByZWZpeDsKKworCQkvKiBub3RoaW5nIHRvIGZvbGQgZm9yIHRoZSBsYXN0IGFyZyBv ciBhIENvbnN0ICovCisJCWlmIChsbmV4dChhcmdzLCBsYykgPT0gTlVMTCB8fCBJc0EoYXJnLCBD b25zdCkpCisJCQljb250aW51ZTsKKworCQl7CisJCQlWYXJpYWJsZVN0YXREYXRhIHZkOworCQkJ ZG91YmxlCQlwX2k7CisKKwkJCWV4YW1pbmVfdmFyaWFibGUocm9vdCwgYXJnLCAwLCAmdmQpOwor CQkJaWYgKCFIZWFwVHVwbGVJc1ZhbGlkKHZkLnN0YXRzVHVwbGUpKQorCQkJeworCQkJCVJlbGVh c2VWYXJpYWJsZVN0YXRzKHZkKTsKKwkJCQlyZXR1cm4gZmFsc2U7CisJCQl9CisJCQlwX2kgPSAo KEZvcm1fcGdfc3RhdGlzdGljKSBHRVRTVFJVQ1QodmQuc3RhdHNUdXBsZSkpLT5zdGFudWxsZnJh YzsKKwkJCVJlbGVhc2VWYXJpYWJsZVN0YXRzKHZkKTsKKworCQkJaWYgKHBfaSA8IDAuMCB8fCBw X2kgPiAxLjApCisJCQkJcmV0dXJuIGZhbHNlOworCisJCQlwcmVmaXggKj0gcF9pOworCQl9CisJ fQorCisJcmV0dXJuIHRydWU7Cit9CisKKy8qCisgKiBDb21tb24gZ3V0cyBvZiBlcXNlbC9lcWpv aW5zZWwgd2hlbiBvbmUgb3IgYm90aCBvcGVyYW5kcyBhcmUgQ29hbGVzY2VFeHByLgorICogQ29t cHV0ZXM6CisgKgorICogICBzZWwoQ09BTEVTQ0UobF8xLC4uLixsX00pID0gQ09BTEVTQ0Uocl8x LC4uLixyX04pKSA9CisgKiAgICAgICBTdW1fe2ksan0gIFBfTChyZWFjaCBpKSAqIFBfUihyZWFj aCBqKSAqIHNlbChsX2kgPSByX2opCisgKgorICogd2hlcmUgUChyZWFjaCBpKSA9IFByb2Rfe2o8 aX0gc3RhbnVsbGZyYWMoYXJnX2opLiAgQSBub24tQ09BTEVTQ0Ugb3BlcmFuZAorICogaXMgdHJl YXRlZCBhcyBhIHNpbmdsZS1lbGVtZW50IGxpc3QuCisgKi8KK3N0YXRpYyBib29sCit0cnlfY29h bGVzY2VfZXEoUEdfRlVOQ1RJT05fQVJHUywgZG91YmxlICpzZWxlY19vdXQpCit7CisJUGxhbm5l ckluZm8gKnJvb3QgPSAoUGxhbm5lckluZm8gKikgUEdfR0VUQVJHX1BPSU5URVIoMCk7CisJT2lk CQkJb3BlcmF0b3IgPSBQR19HRVRBUkdfT0lEKDEpOworCUxpc3QJICAgKmFyZ3MgPSAoTGlzdCAq KSBQR19HRVRBUkdfUE9JTlRFUigyKTsKKwlib29sCQlpc19lcWpvaW4gPSAoZmNpbmZvLT5mbGlu Zm8gIT0gTlVMTCAmJgorCQkJCQkJCSBmY2luZm8tPmZsaW5mby0+Zm5fb2lkID09IEZfRVFKT0lO U0VMKTsKKwlTcGVjaWFsSm9pbkluZm8gKnNqaW5mbyA9IGlzX2Vxam9pbiA/CisJCShTcGVjaWFs Sm9pbkluZm8gKikgUEdfR0VUQVJHX1BPSU5URVIoNCkgOiBOVUxMOworCWludAkJCWVxc2VsX3Zh clJlbGlkID0gaXNfZXFqb2luID8gMCA6IFBHX0dFVEFSR19JTlQzMigzKTsKKwlPaWQJCQljb2xs YXRpb24gPSBQR19HRVRfQ09MTEFUSU9OKCk7CisJTm9kZQkgICAqbGVmdDsKKwlOb2RlCSAgICpy aWdodDsKKwlMaXN0CSAgICpsZWZ0X2FyZ3MgPSBOSUw7CisJTGlzdAkgICAqcmlnaHRfYXJncyA9 IE5JTDsKKwlib29sCQlsZWZ0X2lzX2NvYWxlc2NlOworCWJvb2wJCXJpZ2h0X2lzX2NvYWxlc2Nl OworCWJvb2wJCWxlZnRfdGVybV9jb25zdCA9IGZhbHNlOworCWJvb2wJCXJpZ2h0X3Rlcm1fY29u c3QgPSBmYWxzZTsKKwlkb3VibGUJICAgKmxlZnRfcHJlZml4OworCWRvdWJsZQkgICAqcmlnaHRf cHJlZml4OworCWRvdWJsZQkJYWNjX3NlbGVjID0gMC4wOworCUxpc3RDZWxsICAgKmxsYzsKKwlp bnQJCQlsaTsKKworCWlmIChsaXN0X2xlbmd0aChhcmdzKSAhPSAyKQorCQlyZXR1cm4gZmFsc2U7 CisKKwlsZWZ0ID0gKE5vZGUgKikgbGluaXRpYWwoYXJncyk7CisJcmlnaHQgPSAoTm9kZSAqKSBs c2Vjb25kKGFyZ3MpOworCisJbGVmdF9pc19jb2FsZXNjZSA9IG1hdGNoX2NvYWxlc2NlX2pvaW5f c2lkZShsZWZ0LCAmbGVmdF9hcmdzLAorCQkJCQkJCQkJCQkJJmxlZnRfdGVybV9jb25zdCk7CisJ cmlnaHRfaXNfY29hbGVzY2UgPSBtYXRjaF9jb2FsZXNjZV9qb2luX3NpZGUocmlnaHQsICZyaWdo dF9hcmdzLAorCQkJCQkJCQkJCQkJICZyaWdodF90ZXJtX2NvbnN0KTsKKworCWlmICghbGVmdF9p c19jb2FsZXNjZSAmJiAhcmlnaHRfaXNfY29hbGVzY2UpCisJCXJldHVybiBmYWxzZTsKKworCS8q IG9uZSBzaWRlIGlzIGEgQ29hbGVzY2VFeHByIHRoYXQgbWF0Y2hfY29hbGVzY2Vfam9pbl9zaWRl IHJlamVjdGVkICovCisJaWYgKChsZWZ0X2lzX2NvYWxlc2NlICYmICFyaWdodF9pc19jb2FsZXNj ZSAmJiBJc0EocmlnaHQsIENvYWxlc2NlRXhwcikpIHx8CisJCShyaWdodF9pc19jb2FsZXNjZSAm JiAhbGVmdF9pc19jb2FsZXNjZSAmJiBJc0EobGVmdCwgQ29hbGVzY2VFeHByKSkpCisJeworCQls aXN0X2ZyZWUobGVmdF9hcmdzKTsKKwkJbGlzdF9mcmVlKHJpZ2h0X2FyZ3MpOworCQlyZXR1cm4g ZmFsc2U7CisJfQorCisJaWYgKCFsZWZ0X2lzX2NvYWxlc2NlKQorCXsKKwkJbGVmdF9hcmdzID0g bGlzdF9tYWtlMShsZWZ0KTsKKwkJbGVmdF90ZXJtX2NvbnN0ID0gSXNBKGxlZnQsIENvbnN0KTsK Kwl9CisJaWYgKCFyaWdodF9pc19jb2FsZXNjZSkKKwl7CisJCXJpZ2h0X2FyZ3MgPSBsaXN0X21h a2UxKHJpZ2h0KTsKKwkJcmlnaHRfdGVybV9jb25zdCA9IElzQShyaWdodCwgQ29uc3QpOworCX0K KworCWlmIChpc19lcWpvaW4gJiYgbGVmdF90ZXJtX2NvbnN0ICYmIHJpZ2h0X3Rlcm1fY29uc3Qp CisJeworCQlsaXN0X2ZyZWUobGVmdF9hcmdzKTsKKwkJbGlzdF9mcmVlKHJpZ2h0X2FyZ3MpOwor CQlyZXR1cm4gZmFsc2U7CisJfQorCisJbGVmdF9wcmVmaXggPSAoZG91YmxlICopIHBhbGxvYyhz aXplb2YoZG91YmxlKSAqIGxpc3RfbGVuZ3RoKGxlZnRfYXJncykpOworCXJpZ2h0X3ByZWZpeCA9 IChkb3VibGUgKikgcGFsbG9jKHNpemVvZihkb3VibGUpICogbGlzdF9sZW5ndGgocmlnaHRfYXJn cykpOworCisJaWYgKCFnZXRfY29hbGVzY2VfcHJlZml4X3Byb2JzKHJvb3QsIGxlZnRfYXJncywg bGVmdF9wcmVmaXgpIHx8CisJCSFnZXRfY29hbGVzY2VfcHJlZml4X3Byb2JzKHJvb3QsIHJpZ2h0 X2FyZ3MsIHJpZ2h0X3ByZWZpeCkpCisJeworCQlwZnJlZShsZWZ0X3ByZWZpeCk7CisJCXBmcmVl KHJpZ2h0X3ByZWZpeCk7CisJCWxpc3RfZnJlZShsZWZ0X2FyZ3MpOworCQlsaXN0X2ZyZWUocmln aHRfYXJncyk7CisJCXJldHVybiBmYWxzZTsKKwl9CisKKwlsaSA9IDA7CisJZm9yZWFjaChsbGMs IGxlZnRfYXJncykKKwl7CisJCU5vZGUJICAgKmxhcmcgPSAoTm9kZSAqKSBsZmlyc3QobGxjKTsK KwkJYm9vbAkJbGNvbnN0ID0gSXNBKGxhcmcsIENvbnN0KTsKKwkJTGlzdENlbGwgICAqcmxjOwor CQlpbnQJCQlyaSA9IDA7CisKKwkJaWYgKGxlZnRfcHJlZml4W2xpXSA8IDEuMGUtMTIpCisJCQli cmVhazsKKworCQlmb3JlYWNoKHJsYywgcmlnaHRfYXJncykKKwkJeworCQkJTm9kZQkgICAqcmFy ZyA9IChOb2RlICopIGxmaXJzdChybGMpOworCQkJYm9vbAkJcmNvbnN0ID0gSXNBKHJhcmcsIENv bnN0KTsKKwkJCUxpc3QJICAgKnN1Yl9hcmdzOworCQkJU2VsZWN0aXZpdHkgY29udHJpYjsKKwor CQkJaWYgKHJpZ2h0X3ByZWZpeFtyaV0gPCAxLjBlLTEyKQorCQkJCWJyZWFrOworCisJCQlzdWJf YXJncyA9IGxpc3RfbWFrZTIoY29weU9iamVjdChsYXJnKSwgY29weU9iamVjdChyYXJnKSk7CisK KwkJCWlmICghaXNfZXFqb2luIHx8IGxjb25zdCB8fCByY29uc3QpCisJCQl7CisJCQkJY29udHJp YiA9IERhdHVtR2V0RmxvYXQ4KERpcmVjdEZ1bmN0aW9uQ2FsbDRDb2xsKGVxc2VsLAorCQkJCQkJ CQkJCQkJCQkJCSBjb2xsYXRpb24sCisJCQkJCQkJCQkJCQkJCQkJIFBvaW50ZXJHZXREYXR1bShy b290KSwKKwkJCQkJCQkJCQkJCQkJCQkgT2JqZWN0SWRHZXREYXR1bShvcGVyYXRvciksCisJCQkJ CQkJCQkJCQkJCQkJIFBvaW50ZXJHZXREYXR1bShzdWJfYXJncyksCisJCQkJCQkJCQkJCQkJCQkJ IEludDMyR2V0RGF0dW0oZXFzZWxfdmFyUmVsaWQpKSk7CisJCQl9CisJCQllbHNlCisJCQl7CisJ CQkJY29udHJpYiA9IERhdHVtR2V0RmxvYXQ4KERpcmVjdEZ1bmN0aW9uQ2FsbDVDb2xsKGVxam9p bnNlbCwKKwkJCQkJCQkJCQkJCQkJCQkgY29sbGF0aW9uLAorCQkJCQkJCQkJCQkJCQkJCSBQb2lu dGVyR2V0RGF0dW0ocm9vdCksCisJCQkJCQkJCQkJCQkJCQkJIE9iamVjdElkR2V0RGF0dW0ob3Bl cmF0b3IpLAorCQkJCQkJCQkJCQkJCQkJCSBQb2ludGVyR2V0RGF0dW0oc3ViX2FyZ3MpLAorCQkJ CQkJCQkJCQkJCQkJCSBJbnQxNkdldERhdHVtKEpPSU5fSU5ORVIpLAorCQkJCQkJCQkJCQkJCQkJ CSBQb2ludGVyR2V0RGF0dW0oc2ppbmZvKSkpOworCQkJfQorCisJCQlDTEFNUF9QUk9CQUJJTElU WShjb250cmliKTsKKwkJCWFjY19zZWxlYyArPSBsZWZ0X3ByZWZpeFtsaV0gKiByaWdodF9wcmVm aXhbcmldICogY29udHJpYjsKKworCQkJbGlzdF9mcmVlKHN1Yl9hcmdzKTsKKwkJCXJpKys7CisJ CX0KKworCQlsaSsrOworCX0KKworCXBmcmVlKGxlZnRfcHJlZml4KTsKKwlwZnJlZShyaWdodF9w cmVmaXgpOworCWxpc3RfZnJlZShsZWZ0X2FyZ3MpOworCWxpc3RfZnJlZShyaWdodF9hcmdzKTsK KworCUNMQU1QX1BST0JBQklMSVRZKGFjY19zZWxlYyk7CisJKnNlbGVjX291dCA9IGFjY19zZWxl YzsKKwlyZXR1cm4gdHJ1ZTsKK30KKwogLyoKICAqIENvbW1vbiBjb2RlIGZvciBlcXNlbCgpIGFu ZCBuZXFzZWwoKQogICovCkBAIC0zMTgsNiArNTkwLDkgQEAgZXFzZWxfaW50ZXJuYWwoUEdfRlVO Q1RJT05fQVJHUywgYm9vbCBuZWdhdGUpCiAJYm9vbAkJdmFyb25sZWZ0OwogCWRvdWJsZQkJc2Vs ZWM7CiAKKwlpZiAodHJ5X2NvYWxlc2NlX2VxKGZjaW5mbywgJnNlbGVjKSkKKwkJcmV0dXJuIHNl bGVjOworCiAJLyoKIAkgKiBXaGVuIGFza2VkIGFib3V0IDw+LCB3ZSBkbyB0aGUgZXN0aW1hdGlv biB1c2luZyB0aGUgY29ycmVzcG9uZGluZyA9CiAJICogb3BlcmF0b3IsIHRoZW4gY29udmVydCB0 byA8PiB2aWEgIjEuMCAtIGVxX3NlbGVjdGl2aXR5IC0gbnVsbGZyYWMiLgpAQCAtMjQxOCw2ICsy NjkzLDkgQEAgZXFqb2luc2VsKFBHX0ZVTkNUSU9OX0FSR1MpCiAJYm9vbAkJam9pbl9pc19yZXZl cnNlZDsKIAlSZWxPcHRJbmZvICppbm5lcl9yZWw7CiAKKwlpZiAodHJ5X2NvYWxlc2NlX2VxKGZj aW5mbywgJnNlbGVjKSkKKwkJUEdfUkVUVVJOX0ZMT0FUOCgoZmxvYXQ4KSBzZWxlYyk7CisKIAln ZXRfam9pbl92YXJpYWJsZXMocm9vdCwgYXJncywgc2ppbmZvLAogCQkJCQkgICAmdmFyZGF0YTEs ICZ2YXJkYXRhMiwgJmpvaW5faXNfcmV2ZXJzZWQpOwogCkBAIC00Mzc0LDYgKzQ2NTIsMTU0IEBA IGVzdGltYXRlX211bHRpdmFyaWF0ZV9idWNrZXRzaXplKFBsYW5uZXJJbmZvICpyb290LCBSZWxP cHRJbmZvICppbm5lciwKIAlyZXR1cm4gb3RoZXJjbGF1c2VzOwogfQogCisvKgorICogTW9zdC1j b21tb24tdmFsdWUgZnJlcXVlbmN5IGZvciB2YXJkYXRhLiAgRmFsbHMgYmFjayB0byAxL250dXBs ZXMgd2hlbgorICogb25seSBhIGhpc3RvZ3JhbSBzbG90IGlzIHByZXNlbnQuICBSZXR1cm5zIDAu MCBpZiBubyBzdGF0aXN0aWNzIGFyZQorICogYXZhaWxhYmxlLgorICovCitzdGF0aWMgdm9pZAor Z2V0X3ZhcmlhYmxlX21jdl9mcmVxKFZhcmlhYmxlU3RhdERhdGEgKnZhcmRhdGEsIFNlbGVjdGl2 aXR5ICptY3ZfZnJlcSkKK3sKKwlBdHRTdGF0c1Nsb3Qgc3Nsb3Q7CisKKwkqbWN2X2ZyZXEgPSAw LjA7CisKKwlpZiAoIUhlYXBUdXBsZUlzVmFsaWQodmFyZGF0YS0+c3RhdHNUdXBsZSkpCisJCXJl dHVybjsKKworCWlmIChnZXRfYXR0c3RhdHNzbG90KCZzc2xvdCwgdmFyZGF0YS0+c3RhdHNUdXBs ZSwKKwkJCQkJCSBTVEFUSVNUSUNfS0lORF9NQ1YsIEludmFsaWRPaWQsCisJCQkJCQkgQVRUU1RB VFNTTE9UX05VTUJFUlMpKQorCXsKKwkJaWYgKHNzbG90Lm5udW1iZXJzID4gMCkKKwkJCSptY3Zf ZnJlcSA9IHNzbG90Lm51bWJlcnNbMF07CisJCWZyZWVfYXR0c3RhdHNzbG90KCZzc2xvdCk7CisJ fQorCWVsc2UgaWYgKGdldF9hdHRzdGF0c3Nsb3QoJnNzbG90LCB2YXJkYXRhLT5zdGF0c1R1cGxl LAorCQkJCQkJCSAgU1RBVElTVElDX0tJTkRfSElTVE9HUkFNLCBJbnZhbGlkT2lkLAorCQkJCQkJ CSAgMCkpCisJeworCQkvKiBubyBNQ1ZzIGJ1dCBoaXN0b2dyYW0gcHJlc2VudDogY29sdW1uIGlz IGxpa2VseSB1bmlxdWUgKi8KKwkJaWYgKHZhcmRhdGEtPnJlbCAmJiB2YXJkYXRhLT5yZWwtPnR1 cGxlcyA+IDApCisJCQkqbWN2X2ZyZXEgPSAxLjAgLyB2YXJkYXRhLT5yZWwtPnR1cGxlczsKKwl9 Cit9CisKKy8qCisgKiBFc3RpbWF0ZSBidWNrZXQgc3RhdHMgZm9yIGEgQ29hbGVzY2VFeHByIGhh c2hrZXkgd2hlbiBleGFtaW5lX3ZhcmlhYmxlKCkKKyAqIHJldHVybmVkIGEgZGVmYXVsdCBuZGlz dGluY3QuICBVc2VzIHBlci1icmFuY2ggbmRpc3RpbmN0IGFuZCBtY3ZfZnJlcSwKKyAqIHdlaWdo dGVkIGJ5IG51bGwgZmFsbC10aHJvdWdoIHByb2JhYmlsaXR5LgorICovCitzdGF0aWMgYm9vbAor aGFzaF9idWNrZXRfc3RhdHNfY29hbGVzY2VfZGlzcGF0Y2goUGxhbm5lckluZm8gKnJvb3QsCisJ CQkJCQkJCQlOb2RlICpoYXNoa2V5LAorCQkJCQkJCQkJZG91YmxlIG5idWNrZXRzLAorCQkJCQkJ CQkJU2VsZWN0aXZpdHkgKm1jdl9mcmVxLAorCQkJCQkJCQkJU2VsZWN0aXZpdHkgKmJ1Y2tldHNp emVfZnJhYykKK3sKKwlMaXN0CSAgICpzdHJpcHBlZF9hcmdzOworCWJvb2wJCXRlcm1pbmF0ZXNf d2l0aF9jb25zdDsKKwlkb3VibGUJICAgKnByZWZpeDsKKwlpbnQJCQluYXJnczsKKwlpbnQJCQlp OworCUxpc3RDZWxsICAgKmxjOworCWRvdWJsZQkJbmRfbWl4ID0gMC4wOworCVNlbGVjdGl2aXR5 IG1jdl9taXggPSAwLjA7CisJZG91YmxlCQlyZWxfcm93c19wcm94eSA9IDAuMDsKKwlkb3VibGUJ CXJlbF90dXBsZXNfcHJveHkgPSAwLjA7CisJZG91YmxlCQllc3RmcmFjdDsKKworCWlmICghbWF0 Y2hfY29hbGVzY2Vfam9pbl9zaWRlKGhhc2hrZXksICZzdHJpcHBlZF9hcmdzLCAmdGVybWluYXRl c193aXRoX2NvbnN0KSkKKwkJcmV0dXJuIGZhbHNlOworCisJbmFyZ3MgPSBsaXN0X2xlbmd0aChz dHJpcHBlZF9hcmdzKTsKKwlwcmVmaXggPSAoZG91YmxlICopIHBhbGxvYyhzaXplb2YoZG91Ymxl KSAqIG5hcmdzKTsKKworCWlmICghZ2V0X2NvYWxlc2NlX3ByZWZpeF9wcm9icyhyb290LCBzdHJp cHBlZF9hcmdzLCBwcmVmaXgpKQorCXsKKwkJcGZyZWUocHJlZml4KTsKKwkJbGlzdF9mcmVlKHN0 cmlwcGVkX2FyZ3MpOworCQlyZXR1cm4gZmFsc2U7CisJfQorCisJaSA9IDA7CisJZm9yZWFjaChs Yywgc3RyaXBwZWRfYXJncykKKwl7CisJCU5vZGUJICAgKmFyZyA9IChOb2RlICopIGxmaXJzdChs Yyk7CisKKwkJaWYgKElzQShhcmcsIENvbnN0KSkKKwkJeworCQkJbWN2X21peCA9IE1heChtY3Zf bWl4LCBwcmVmaXhbaV0pOworCQkJaWYgKHByZWZpeFtpXSA+IDAuMCkKKwkJCQluZF9taXggKz0g MS4wOworCQl9CisJCWVsc2UKKwkJeworCQkJVmFyaWFibGVTdGF0RGF0YSB2ZDsKKwkJCWRvdWJs ZQkJbmRfaTsKKwkJCWJvb2wJCWlzZGVmYXVsdDsKKwkJCVNlbGVjdGl2aXR5IG1jdl9pOworCisJ CQlleGFtaW5lX3ZhcmlhYmxlKHJvb3QsIGFyZywgMCwgJnZkKTsKKwkJCW5kX2kgPSBnZXRfdmFy aWFibGVfbnVtZGlzdGluY3QoJnZkLCAmaXNkZWZhdWx0KTsKKworCQkJaWYgKGlzZGVmYXVsdCkK KwkJCXsKKwkJCQlSZWxlYXNlVmFyaWFibGVTdGF0cyh2ZCk7CisJCQkJcGZyZWUocHJlZml4KTsK KwkJCQlsaXN0X2ZyZWUoc3RyaXBwZWRfYXJncyk7CisJCQkJcmV0dXJuIGZhbHNlOworCQkJfQor CisJCQlnZXRfdmFyaWFibGVfbWN2X2ZyZXEoJnZkLCAmbWN2X2kpOworCisJCQluZF9taXggPSBN YXgobmRfbWl4LCBuZF9pKTsKKwkJCW1jdl9taXggPSBNYXgobWN2X21peCwgcHJlZml4W2ldICog bWN2X2kpOworCisJCQlpZiAoaSA9PSAwICYmIHZkLnJlbCAmJiB2ZC5yZWwtPnR1cGxlcyA+IDAp CisJCQl7CisJCQkJcmVsX3Jvd3NfcHJveHkgPSB2ZC5yZWwtPnJvd3M7CisJCQkJcmVsX3R1cGxl c19wcm94eSA9IHZkLnJlbC0+dHVwbGVzOworCQkJfQorCisJCQlSZWxlYXNlVmFyaWFibGVTdGF0 cyh2ZCk7CisJCX0KKworCQlpKys7CisJfQorCisJcGZyZWUocHJlZml4KTsKKwlsaXN0X2ZyZWUo c3RyaXBwZWRfYXJncyk7CisKKwlpZiAocmVsX3R1cGxlc19wcm94eSA+IDAuMCkKKwl7CisJCW5k X21peCAqPSByZWxfcm93c19wcm94eSAvIHJlbF90dXBsZXNfcHJveHk7CisJCW5kX21peCA9IGNs YW1wX3Jvd19lc3QobmRfbWl4KTsKKwl9CisKKwlpZiAobmRfbWl4IDw9IDAuMCkKKwkJcmV0dXJu IGZhbHNlOworCisJaWYgKG5kX21peCA+IG5idWNrZXRzKQorCQllc3RmcmFjdCA9IDEuMCAvIG5i dWNrZXRzOworCWVsc2UKKwkJZXN0ZnJhY3QgPSAxLjAgLyBuZF9taXg7CisKKwlDTEFNUF9QUk9C QUJJTElUWShtY3ZfbWl4KTsKKwkqbWN2X2ZyZXEgPSBNYXgoKm1jdl9mcmVxLCBtY3ZfbWl4KTsK KwlDTEFNUF9QUk9CQUJJTElUWSgqbWN2X2ZyZXEpOworCWVzdGZyYWN0ID0gTWF4KGVzdGZyYWN0 LCAqbWN2X2ZyZXEpOworCisJaWYgKGVzdGZyYWN0IDwgMS4wZS02KQorCQllc3RmcmFjdCA9IDEu MGUtNjsKKwllbHNlIGlmIChlc3RmcmFjdCA+IDEuMCkKKwkJZXN0ZnJhY3QgPSAxLjA7CisKKwkq YnVja2V0c2l6ZV9mcmFjID0gKFNlbGVjdGl2aXR5KSBlc3RmcmFjdDsKKworCXJldHVybiB0cnVl OworfQorCiAvKgogICogRXN0aW1hdGUgaGFzaCBidWNrZXQgc3RhdGlzdGljcyB3aGVuIHRoZSBz cGVjaWZpZWQgZXhwcmVzc2lvbiBpcyB1c2VkCiAgKiBhcyBhIGhhc2gga2V5IGZvciB0aGUgZ2l2 ZW4gbnVtYmVyIG9mIGJ1Y2tldHMuCkBAIC00NDI3LDQzICs0ODUzLDIxIEBAIGVzdGltYXRlX2hh c2hfYnVja2V0X3N0YXRzKFBsYW5uZXJJbmZvICpyb290LCBOb2RlICpoYXNoa2V5LCBkb3VibGUg bmJ1Y2tldHMsCiAJZG91YmxlCQllc3RmcmFjdCwKIAkJCQluZGlzdGluY3Q7CiAJYm9vbAkJaXNk ZWZhdWx0OwotCUF0dFN0YXRzU2xvdCBzc2xvdDsKIAogCWV4YW1pbmVfdmFyaWFibGUocm9vdCwg aGFzaGtleSwgMCwgJnZhcmRhdGEpOwogCi0JLyogSW5pdGlhbGl6ZSAqbWN2X2ZyZXEgdG8gInVu a25vd24iICovCi0JKm1jdl9mcmVxID0gMC4wOwotCi0JLyogTG9vayB1cCB0aGUgZnJlcXVlbmN5 IG9mIHRoZSBtb3N0IGNvbW1vbiB2YWx1ZSwgaWYgYXZhaWxhYmxlICovCi0JaWYgKEhlYXBUdXBs ZUlzVmFsaWQodmFyZGF0YS5zdGF0c1R1cGxlKSkKLQl7Ci0JCWlmIChnZXRfYXR0c3RhdHNzbG90 KCZzc2xvdCwgdmFyZGF0YS5zdGF0c1R1cGxlLAotCQkJCQkJCSBTVEFUSVNUSUNfS0lORF9NQ1Ys IEludmFsaWRPaWQsCi0JCQkJCQkJIEFUVFNUQVRTU0xPVF9OVU1CRVJTKSkKLQkJewotCQkJLyoK LQkJCSAqIFRoZSBmaXJzdCBNQ1Ygc3RhdCBpcyBmb3IgdGhlIG1vc3QgY29tbW9uIHZhbHVlLgot CQkJICovCi0JCQlpZiAoc3Nsb3Qubm51bWJlcnMgPiAwKQotCQkJCSptY3ZfZnJlcSA9IHNzbG90 Lm51bWJlcnNbMF07Ci0JCQlmcmVlX2F0dHN0YXRzc2xvdCgmc3Nsb3QpOwotCQl9Ci0JCWVsc2Ug aWYgKGdldF9hdHRzdGF0c3Nsb3QoJnNzbG90LCB2YXJkYXRhLnN0YXRzVHVwbGUsCi0JCQkJCQkJ CSAgU1RBVElTVElDX0tJTkRfSElTVE9HUkFNLCBJbnZhbGlkT2lkLAotCQkJCQkJCQkgIDApKQot CQl7Ci0JCQkvKgotCQkJICogSWYgdGhlcmUgYXJlIG5vIHJlY29yZGVkIE1DVnMsIGJ1dCB3ZSBk byBoYXZlIGEgaGlzdG9ncmFtLCB0aGVuCi0JCQkgKiBhc3N1bWUgdGhhdCBBTkFMWVpFIGRldGVy bWluZWQgdGhhdCB0aGUgY29sdW1uIGlzIHVuaXF1ZS4KLQkJCSAqLwotCQkJaWYgKHZhcmRhdGEu cmVsICYmIHZhcmRhdGEucmVsLT50dXBsZXMgPiAwKQotCQkJCSptY3ZfZnJlcSA9IDEuMCAvIHZh cmRhdGEucmVsLT50dXBsZXM7Ci0JCX0KLQl9CisJZ2V0X3ZhcmlhYmxlX21jdl9mcmVxKCZ2YXJk YXRhLCBtY3ZfZnJlcSk7CiAKIAkvKiBHZXQgbnVtYmVyIG9mIGRpc3RpbmN0IHZhbHVlcyAqLwog CW5kaXN0aW5jdCA9IGdldF92YXJpYWJsZV9udW1kaXN0aW5jdCgmdmFyZGF0YSwgJmlzZGVmYXVs dCk7CiAKKwlpZiAoaXNkZWZhdWx0ICYmIGhhc2hfYnVja2V0X3N0YXRzX2NvYWxlc2NlX2Rpc3Bh dGNoKHJvb3QsIGhhc2hrZXksIG5idWNrZXRzLAorCQkJCQkJCQkJCQkJCQkgbWN2X2ZyZXEsIGJ1 Y2tldHNpemVfZnJhYykpCisJeworCQlSZWxlYXNlVmFyaWFibGVTdGF0cyh2YXJkYXRhKTsKKwkJ cmV0dXJuOworCX0KKwogCS8qCiAJICogSWYgbmRpc3RpbmN0IGlzbid0IHJlYWwsIHB1bnQuICBX ZSBub3JtYWxseSByZXR1cm4gMC4xLCBidXQgaWYgdGhlCiAJICogbWN2X2ZyZXEgaXMga25vd24g dG8gYmUgZXZlbiBoaWdoZXIgdGhhbiB0aGF0LCB1c2UgaXQgaW5zdGVhZC4K --000000000000f1c10d065576d722--