Blame SOURCES/perl-5.30.0-PATCH-perl-134329-Use-after-free-in-regcomp.c.patch

7586d2
From fd30a7c49a661aecfb361045646da264cdadea8f Mon Sep 17 00:00:00 2001
7586d2
From: Karl Williamson <khw@cpan.org>
7586d2
Date: Fri, 23 Aug 2019 12:40:24 -0600
7586d2
Subject: [PATCH] PATCH: [perl #134329] Use after free in regcomp.c
7586d2
MIME-Version: 1.0
7586d2
Content-Type: text/plain; charset=UTF-8
7586d2
Content-Transfer-Encoding: 8bit
7586d2
7586d2
A compiled regex is composed of nodes, forming a linked list, with
7586d2
normally a maximum of 16 bits used to specify the offset of the next
7586d2
link.  For patterns that require more space than this, the nodes that
7586d2
jump around are replaced with ones that have wider offsets.  Most nodes
7586d2
are unaffected, as they just contain the offset of the next node, and
7586d2
that number is always small.  The jump nodes are the ones affected.
7586d2
7586d2
When compiling a pattern, the 16 bit mechanism is used, until it
7586d2
overflows, at which point the pattern is recompiled with the long jumps
7586d2
instead.
7586d2
7586d2
When I rewrote the compiler last year to make it generally one pass, I
7586d2
noticed a lot of the cases where a node was added didn't check if the
7586d2
result overflowed (the function that does this returns FALSE in that
7586d2
case).  I presumed the prior authors knew better, and did not change
7586d2
things, except to put in a bogus value in the link (offset) field that
7586d2
should cause a crash if it were used.  That's what's happening in this
7586d2
ticket.
7586d2
7586d2
But seeing this example, it's clear that the return value should be
7586d2
checked every time, because you can reach the limit at any time.  This
7586d2
commit changes to do that, and to require the function's return value to
7586d2
not be ignored, to guard against future changes.
7586d2
7586d2
My guess is that the reason it generally worked when there were multiple
7586d2
passes is that the first pass didn't do anything except count space, and
7586d2
that at some point before the end of the pass the return value did get
7586d2
checked, so by the time the nodes were allocated for real, it knew
7586d2
enough to use the long jumps.
7586d2
7586d2
Petr Písař: Ported to 5.30.0 from
7586d2
3b2e5620ed4a6b341f97ffd1d4b6466cc2c4bc5b.
7586d2
7586d2
Signed-off-by: Petr Písař <ppisar@redhat.com>
7586d2
---
7586d2
 MANIFEST                 |   1 +
7586d2
 embed.fnc                |   4 +-
7586d2
 proto.h                  |   8 ++-
7586d2
 regcomp.c                | 109 ++++++++++++++++++++++++++++-----------
7586d2
 t/re/bigfuzzy_not_utf8.t | Bin 0 -> 36399 bytes
7586d2
 5 files changed, 88 insertions(+), 34 deletions(-)
7586d2
 create mode 100644 t/re/bigfuzzy_not_utf8.t
7586d2
7586d2
diff --git a/MANIFEST b/MANIFEST
7586d2
index 10e2cc0..cc24cd7 100644
7586d2
--- a/MANIFEST
7586d2
+++ b/MANIFEST
7586d2
@@ -5839,6 +5839,7 @@ t/porting/test_bootstrap.t	Test that the instructions for test bootstrapping are
7586d2
 t/porting/utils.t		Check that utility scripts still compile
7586d2
 t/re/alpha_assertions.t		See if things like '(*postive_lookahed:...) work properly
7586d2
 t/re/anyof.t			See if bracketed char classes [...] compile properly
7586d2
+t/re/bigfuzzy_not_utf8.t	Big and ugly tests not storable as UTF-8
7586d2
 t/re/charset.t			See if regex modifiers like /d, /u work properly
7586d2
 t/re/fold_grind.pl		Core file to see if regex case folding works properly
7586d2
 t/re/fold_grind_8.t		Wrapper for fold_grind.pl for /l testing with a UTF-8 locale
7586d2
diff --git a/embed.fnc b/embed.fnc
7586d2
index c977d39..c2c5f16 100644
7586d2
--- a/embed.fnc
7586d2
+++ b/embed.fnc
7586d2
@@ -2427,7 +2427,7 @@ Es	|void	|reginsert	|NN RExC_state_t *pRExC_state \
7586d2
 				|const U8 op				    \
7586d2
 				|const regnode_offset operand		    \
7586d2
 				|const U32 depth
7586d2
-Es	|bool	|regtail	|NN RExC_state_t * pRExC_state		    \
7586d2
+EsR	|bool	|regtail	|NN RExC_state_t * pRExC_state		    \
7586d2
 				|NN const regnode_offset p		    \
7586d2
 				|NN const regnode_offset val		    \
7586d2
 				|const U32 depth
7586d2
@@ -2561,7 +2561,7 @@ Es	|void	|dump_trie_interim_list|NN const struct _reg_trie_data *trie\
7586d2
 Es	|void	|dump_trie_interim_table|NN const struct _reg_trie_data *trie\
7586d2
 				|NULLOK HV* widecharmap|NN AV *revcharmap\
7586d2
 				|U32 next_alloc|U32 depth
7586d2
-Es	|bool	|regtail_study	|NN RExC_state_t *pRExC_state \
7586d2
+EsR	|bool	|regtail_study	|NN RExC_state_t *pRExC_state \
7586d2
 				|NN regnode_offset p|NN const regnode_offset val|U32 depth
7586d2
 #  endif
7586d2
 #endif
7586d2
diff --git a/proto.h b/proto.h
7586d2
index e0ea55b..2ef7ce2 100644
7586d2
--- a/proto.h
7586d2
+++ b/proto.h
7586d2
@@ -4457,9 +4457,11 @@ PERL_CALLCONV int	Perl_re_indentf(pTHX_ const char *fmt, U32 depth, ...);
7586d2
 	assert(fmt)
7586d2
 STATIC void	S_regdump_extflags(pTHX_ const char *lead, const U32 flags);
7586d2
 STATIC void	S_regdump_intflags(pTHX_ const char *lead, const U32 flags);
7586d2
-STATIC bool	S_regtail_study(pTHX_ RExC_state_t *pRExC_state, regnode_offset p, const regnode_offset val, U32 depth);
7586d2
+STATIC bool	S_regtail_study(pTHX_ RExC_state_t *pRExC_state, regnode_offset p, const regnode_offset val, U32 depth)
7586d2
+			__attribute__warn_unused_result__;
7586d2
 #define PERL_ARGS_ASSERT_REGTAIL_STUDY	\
7586d2
 	assert(pRExC_state); assert(p); assert(val)
7586d2
+
7586d2
 #  endif
7586d2
 #  if defined(PERL_IN_REGEXEC_C)
7586d2
 STATIC void	S_debug_start_match(pTHX_ const REGEXP *prog, const bool do_utf8, const char *start, const char *end, const char *blurb);
7586d2
@@ -5599,9 +5601,11 @@ STATIC regnode_offset	S_regnode_guts(pTHX_ RExC_state_t *pRExC_state, const U8 o
7586d2
 STATIC regnode_offset	S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth);
7586d2
 #define PERL_ARGS_ASSERT_REGPIECE	\
7586d2
 	assert(pRExC_state); assert(flagp)
7586d2
-STATIC bool	S_regtail(pTHX_ RExC_state_t * pRExC_state, const regnode_offset p, const regnode_offset val, const U32 depth);
7586d2
+STATIC bool	S_regtail(pTHX_ RExC_state_t * pRExC_state, const regnode_offset p, const regnode_offset val, const U32 depth)
7586d2
+			__attribute__warn_unused_result__;
7586d2
 #define PERL_ARGS_ASSERT_REGTAIL	\
7586d2
 	assert(pRExC_state); assert(p); assert(val)
7586d2
+
7586d2
 STATIC void	S_scan_commit(pTHX_ const RExC_state_t *pRExC_state, struct scan_data_t *data, SSize_t *minlenp, int is_inf);
7586d2
 #define PERL_ARGS_ASSERT_SCAN_COMMIT	\
7586d2
 	assert(pRExC_state); assert(data); assert(minlenp)
7586d2
diff --git a/regcomp.c b/regcomp.c
7586d2
index dfc22bc..b93fbe7 100644
7586d2
--- a/regcomp.c
7586d2
+++ b/regcomp.c
7586d2
@@ -11307,10 +11307,15 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
7586d2
                         return 0;
7586d2
                     }
7586d2
 
7586d2
-                    REGTAIL(pRExC_state, ret, atomic);
7586d2
+                    if (! REGTAIL(pRExC_state, ret, atomic)) {
7586d2
+                        REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                    }
7586d2
 
7586d2
-                    REGTAIL(pRExC_state, atomic,
7586d2
-                           reg_node(pRExC_state, SRCLOSE));
7586d2
+                    if (! REGTAIL(pRExC_state, atomic, reg_node(pRExC_state,
7586d2
+                                                                SRCLOSE)))
7586d2
+                    {
7586d2
+                        REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                    }
7586d2
 
7586d2
                     RExC_in_script_run = 0;
7586d2
                     return ret;
7586d2
@@ -11769,7 +11774,9 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
7586d2
                                        RExC_flags & RXf_PMf_COMPILETIME
7586d2
                                       );
7586d2
                     FLAGS(REGNODE_p(ret)) = 2;
7586d2
-                    REGTAIL(pRExC_state, ret, eval);
7586d2
+                    if (! REGTAIL(pRExC_state, ret, eval)) {
7586d2
+                        REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                    }
7586d2
                     /* deal with the length of this later - MJD */
7586d2
 		    return ret;
7586d2
 		}
7586d2
@@ -11822,7 +11829,9 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
7586d2
 
7586d2
                     tail = reg(pRExC_state, 1, &flag, depth+1);
7586d2
                     RETURN_FAIL_ON_RESTART(flag, flagp);
7586d2
-                    REGTAIL(pRExC_state, ret, tail);
7586d2
+                    if (! REGTAIL(pRExC_state, ret, tail)) {
7586d2
+                        REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                    }
7586d2
                     goto insert_if;
7586d2
                 }
7586d2
 		else if (   RExC_parse[0] == '<'     /* (?(<NAME>)...) */
7586d2
@@ -11914,15 +11923,22 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
7586d2
 		    }
7586d2
 		    nextchar(pRExC_state);
7586d2
 		  insert_if:
7586d2
-                    REGTAIL(pRExC_state, ret, reganode(pRExC_state, IFTHEN, 0));
7586d2
+                    if (! REGTAIL(pRExC_state, ret, reganode(pRExC_state,
7586d2
+                                                             IFTHEN, 0)))
7586d2
+                    {
7586d2
+                        REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                    }
7586d2
                     br = regbranch(pRExC_state, &flags, 1, depth+1);
7586d2
 		    if (br == 0) {
7586d2
                         RETURN_FAIL_ON_RESTART(flags,flagp);
7586d2
                         FAIL2("panic: regbranch returned failure, flags=%#" UVxf,
7586d2
                               (UV) flags);
7586d2
                     } else
7586d2
-                        REGTAIL(pRExC_state, br, reganode(pRExC_state,
7586d2
-                                                          LONGJMP, 0));
7586d2
+                    if (! REGTAIL(pRExC_state, br, reganode(pRExC_state,
7586d2
+                                                             LONGJMP, 0)))
7586d2
+                    {
7586d2
+                        REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                    }
7586d2
 		    c = UCHARAT(RExC_parse);
7586d2
                     nextchar(pRExC_state);
7586d2
 		    if (flags&HASWIDTH)
7586d2
@@ -11939,7 +11955,9 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
7586d2
                             FAIL2("panic: regbranch returned failure, flags=%#" UVxf,
7586d2
                                   (UV) flags);
7586d2
                         }
7586d2
-                        REGTAIL(pRExC_state, ret, lastbr);
7586d2
+                        if (! REGTAIL(pRExC_state, ret, lastbr)) {
7586d2
+                            REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                        }
7586d2
 		 	if (flags&HASWIDTH)
7586d2
 			    *flagp |= HASWIDTH;
7586d2
                         c = UCHARAT(RExC_parse);
7586d2
@@ -11954,16 +11972,26 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
7586d2
                             vFAIL("Switch (?(condition)... contains too many branches");
7586d2
                     }
7586d2
 		    ender = reg_node(pRExC_state, TAIL);
7586d2
-                    REGTAIL(pRExC_state, br, ender);
7586d2
+                    if (! REGTAIL(pRExC_state, br, ender)) {
7586d2
+                        REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                    }
7586d2
 		    if (lastbr) {
7586d2
-                        REGTAIL(pRExC_state, lastbr, ender);
7586d2
-                        REGTAIL(pRExC_state, REGNODE_OFFSET(
7586d2
-                                                NEXTOPER(
7586d2
-                                                NEXTOPER(REGNODE_p(lastbr)))),
7586d2
-                                             ender);
7586d2
+                        if (! REGTAIL(pRExC_state, lastbr, ender)) {
7586d2
+                            REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                        }
7586d2
+                        if (! REGTAIL(pRExC_state,
7586d2
+                                      REGNODE_OFFSET(
7586d2
+                                                 NEXTOPER(
7586d2
+                                                 NEXTOPER(REGNODE_p(lastbr)))),
7586d2
+                                      ender))
7586d2
+                        {
7586d2
+                            REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                        }
7586d2
 		    }
7586d2
 		    else
7586d2
-                        REGTAIL(pRExC_state, ret, ender);
7586d2
+                        if (! REGTAIL(pRExC_state, ret, ender)) {
7586d2
+                            REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                        }
7586d2
 #if 0  /* Removing this doesn't cause failures in the test suite -- khw */
7586d2
                     RExC_size++; /* XXX WHY do we need this?!!
7586d2
                                     For large programs it seems to be required
7586d2
@@ -12113,7 +12141,9 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
7586d2
 	*flagp |= flags&SIMPLE;
7586d2
     }
7586d2
     if (is_open) {				/* Starts with OPEN. */
7586d2
-        REGTAIL(pRExC_state, ret, br);          /* OPEN -> first. */
7586d2
+        if (! REGTAIL(pRExC_state, ret, br)) {  /* OPEN -> first. */
7586d2
+            REQUIRE_BRANCHJ(flagp, 0);
7586d2
+        }
7586d2
     }
7586d2
     else if (paren != '?')		/* Not Conditional */
7586d2
 	ret = br;
7586d2
@@ -12121,12 +12151,15 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
7586d2
     lastbr = br;
7586d2
     while (*RExC_parse == '|') {
7586d2
 	if (RExC_use_BRANCHJ) {
7586d2
+            bool shut_gcc_up;
7586d2
+
7586d2
 	    ender = reganode(pRExC_state, LONGJMP, 0);
7586d2
 
7586d2
             /* Append to the previous. */
7586d2
-            REGTAIL(pRExC_state,
7586d2
-                    REGNODE_OFFSET(NEXTOPER(NEXTOPER(REGNODE_p(lastbr)))),
7586d2
-                    ender);
7586d2
+            shut_gcc_up = REGTAIL(pRExC_state,
7586d2
+                         REGNODE_OFFSET(NEXTOPER(NEXTOPER(REGNODE_p(lastbr)))),
7586d2
+                         ender);
7586d2
+            PERL_UNUSED_VAR(shut_gcc_up);
7586d2
 	}
7586d2
 	nextchar(pRExC_state);
7586d2
 	if (freeze_paren) {
7586d2
@@ -12237,9 +12270,10 @@ S_reg(pTHX_ RExC_state_t *pRExC_state, I32 paren, I32 *flagp, U32 depth)
7586d2
                         is_nothing= 0;
7586d2
 		}
7586d2
 		else if (op == BRANCHJ) {
7586d2
-                    REGTAIL_STUDY(pRExC_state,
7586d2
-                                  REGNODE_OFFSET(NEXTOPER(NEXTOPER(br))),
7586d2
-                                  ender);
7586d2
+                    bool shut_gcc_up = REGTAIL_STUDY(pRExC_state,
7586d2
+                                        REGNODE_OFFSET(NEXTOPER(NEXTOPER(br))),
7586d2
+                                        ender);
7586d2
+                    PERL_UNUSED_VAR(shut_gcc_up);
7586d2
                     /* for now we always disable this optimisation * /
7586d2
                     if ( OP(NEXTOPER(NEXTOPER(br))) != NOTHING
7586d2
                          || regnext(NEXTOPER(NEXTOPER(br))) != REGNODE_p(ender))
7586d2
@@ -12551,7 +12585,9 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
7586d2
 		const regnode_offset w = reg_node(pRExC_state, WHILEM);
7586d2
 
7586d2
 		FLAGS(REGNODE_p(w)) = 0;
7586d2
-                REGTAIL(pRExC_state, ret, w);
7586d2
+                if (!  REGTAIL(pRExC_state, ret, w)) {
7586d2
+                    REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                }
7586d2
 		if (RExC_use_BRANCHJ) {
7586d2
 		    reginsert(pRExC_state, LONGJMP, ret, depth+1);
7586d2
 		    reginsert(pRExC_state, NOTHING, ret, depth+1);
7586d2
@@ -12566,7 +12602,11 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
7586d2
 		if (RExC_use_BRANCHJ)
7586d2
                     NEXT_OFF(REGNODE_p(ret)) = 3;   /* Go over NOTHING to
7586d2
                                                        LONGJMP. */
7586d2
-                REGTAIL(pRExC_state, ret, reg_node(pRExC_state, NOTHING));
7586d2
+                if (! REGTAIL(pRExC_state, ret, reg_node(pRExC_state,
7586d2
+                                                          NOTHING)))
7586d2
+                {
7586d2
+                    REQUIRE_BRANCHJ(flagp, 0);
7586d2
+                }
7586d2
                 RExC_whilem_seen++;
7586d2
                 MARK_NAUGHTY_EXP(1, 4);     /* compound interest */
7586d2
 	    }
7586d2
@@ -12638,16 +12678,22 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
7586d2
     if (*RExC_parse == '?') {
7586d2
 	nextchar(pRExC_state);
7586d2
 	reginsert(pRExC_state, MINMOD, ret, depth+1);
7586d2
-        REGTAIL(pRExC_state, ret, ret + NODE_STEP_REGNODE);
7586d2
+        if (! REGTAIL(pRExC_state, ret, ret + NODE_STEP_REGNODE)) {
7586d2
+            REQUIRE_BRANCHJ(flagp, 0);
7586d2
+        }
7586d2
     }
7586d2
     else if (*RExC_parse == '+') {
7586d2
         regnode_offset ender;
7586d2
         nextchar(pRExC_state);
7586d2
         ender = reg_node(pRExC_state, SUCCEED);
7586d2
-        REGTAIL(pRExC_state, ret, ender);
7586d2
+        if (! REGTAIL(pRExC_state, ret, ender)) {
7586d2
+            REQUIRE_BRANCHJ(flagp, 0);
7586d2
+        }
7586d2
         reginsert(pRExC_state, SUSPEND, ret, depth+1);
7586d2
         ender = reg_node(pRExC_state, TAIL);
7586d2
-        REGTAIL(pRExC_state, ret, ender);
7586d2
+        if (! REGTAIL(pRExC_state, ret, ender)) {
7586d2
+            REQUIRE_BRANCHJ(flagp, 0);
7586d2
+        }
7586d2
     }
7586d2
 
7586d2
     if (ISMULT2(RExC_parse)) {
7586d2
@@ -19815,8 +19861,8 @@ S_regtail(pTHX_ RExC_state_t * pRExC_state,
7586d2
     }
7586d2
     else {
7586d2
         if (val - scan > U16_MAX) {
7586d2
-            /* Since not all callers check the return value, populate this with
7586d2
-             * something that won't loop and will likely lead to a crash if
7586d2
+            /* Populate this with something that won't loop and will likely
7586d2
+             * lead to a crash if the caller ignores the failure return, and
7586d2
              * execution continues */
7586d2
             NEXT_OFF(REGNODE_p(scan)) = U16_MAX;
7586d2
             return FALSE;
7586d2
@@ -19927,6 +19973,9 @@ S_regtail_study(pTHX_ RExC_state_t *pRExC_state, regnode_offset p,
7586d2
     }
7586d2
     else {
7586d2
         if (val - scan > U16_MAX) {
7586d2
+            /* Populate this with something that won't loop and will likely
7586d2
+             * lead to a crash if the caller ignores the failure return, and
7586d2
+             * execution continues */
7586d2
             NEXT_OFF(REGNODE_p(scan)) = U16_MAX;
7586d2
             return FALSE;
7586d2
         }
7586d2
diff --git a/t/re/bigfuzzy_not_utf8.t b/t/re/bigfuzzy_not_utf8.t
7586d2
new file mode 100644
7586d2
index 0000000000000000000000000000000000000000..b4dfd150a9297172af5d8e7811357fd68931f8d7
7586d2
GIT binary patch
7586d2
literal 36399
7586d2
zcmeI5y>Ht_6u>V)vj`|)bnw`ot)P-@MMCTpNTQ@6nzlsHpvaKGfa6%8#FNC9CKZxu
7586d2
z;)Jf$YRJ%zoeHDqo_|0?hWr89EXQ;I1&?0XN7}J$MN%l4pVm7V_T9aA@8fqzil1_F
7586d2
zE|;$}O->{eN&28B=@fnhT2nU|t*9E+ShXPw8fDMw8q;-2Rj9#qL#IYfFlbp&QU)zC
7586d2
zsvD}tL@Ma?;e+olU(13qL4mf$Xi2KlMpfR-(n>>?sal~`K`RMWM$0up6UqkD^enA1
7586d2
zg=vB;ZywbQuvXdxGnK~k=b({GBpSNyN0Z7%!KptLG(}RXdLfa}8zrhWl%f+Fv@e
7586d2
z7QF(MZ@%O2{zzXWD3o$dlr)+$QdFwY%c5N?I0B75X-E+19aX7F)dH0^>Z)eEZ=O;~
7586d2
zoje1d1%IQ=tmzSkdDoay2=T|Pz
7586d2
zo*8+Kr80%Y79{wyR4)RabV^adFWpeZh73a5P-K`EDzb{C0J1N?-Bg5osvt7$#*LDy
7586d2
z8pU1*;Hb;O`}w=|H2|VCNgvil!C)|-F!4`oOre4(0@l39WM)9+aK3^6G2ryE+cJd2
7586d2
zG%)O}9%o(Xh5+npOk+9dJvA{f4-S
7586d2
zS%FnoE840>Nl&MqX!&&dnrWK5-2KkXUdJ@kJhZYzBs1%)nFU8yw#)YRc86bC;+Jl5
7586d2
zgy&7Z`^Fw(?OiZUet&)S)$APMGYhtb_713ZrNwu<++Ih39!HYq+wJzw?PH0VT{$4+
7586d2
zz%lmLw7_MJYpy#@2q4sQ7fUP%j9esxG8j3)cOk6*w(m~R0TQqY5H30#e)2t(Pe1U0
7586d2
zo7x9RuwyuZKZc9WF8Sr`COoz9_eZT+t&ggp!nq?r$P9^7Qf{`Z-{X`J#)<@xfTsj3
7586d2
zt7*Z}u%|ZB*f}Q9ILEnRY6A%n(u&6pLLV6Zhn*Je^046bHe3TpU@8gBV?hE)AbtcU
7586d2
z+*`#j(Lf`1Pqq2ly)J6Thrs2aLgj*Tgns-Zu;!m>A1&i8UmxMd)HGfL@L=Np^}xmu
7586d2
z6KnnbWTw9d+eiQj_)Fjmf6b$HBoG*ZvmFNFos+;OYFZqXdWnYd{P*jg`)Jij({(%|
7586d2
z`6Q@2v~b4IiYzkMz+$L)vsWgF{`mxB#u(y$sg7Y3RpU)yZB+QhQ9`d|Ekc6YFM1X7
7586d2
zv7KL!Yu;A|z5IoJ9um0Yp{;0|@_teFTYTByaiWdaEl
7586d2
zPFzulaPT39=F90?E5wAR)%Dpf=7vno3fVuppO8Ro&#5QO7l$E%7!gQ^8*6kwlia=^
7586d2
z7B0VddLMEq9(*#931rOF{~Aj_u33(iBr5k4z;mpAB2(G^Zz{9Kq>+G^1Vp#S{&b=E
7586d2
zj|&}JWy0IK6Ap73lq)qn<QR$RqGeqiso;SyjOXJ#2pdfx0VLp>z?y5#A&T&w
7586d2
zUiJx|1$vwg0zrO}lpkL`u+~3K_
7586d2
zicZin*SoHPf#Jg+1F=k5r(avNUv|&?^aT4NA<j}5>#6r1;mt7IkM
7586d2
zl=}L=Xoe&f=@$t@+-3rNH|>W2eFfxdF(5w^x}jvkffEfIvgHNTjXV5+K%<*L3ET_R
7586d2
z+c|c&wL;;PQ@lgr#v_H=NB{{Sfw2f&z<1F4c?Err>gK7){ur^11cD`i`-xzApY~Qf
7586d2
z-Soco%zKmLS;Xfudc5$tj2??=s^NXSD9!fSp38_*Cb5m>t!bHAQk&zN(xREQTJ4>c
7586d2
zC4OI8w7BN_>Y<Q`P|Yl)JEqC+?<=onyWQ@36FPXvI!i<{<A|?8t9(>=zWZjEyWg?)
7586d2
z-~n%be|`1U>>S}U3wvP0@z9kP-|cdH9RYeANt%btP&>Dm_#=s#T{$4+fFnF_9>oX|
7586d2
zooo&c`N+|sIY^}|4akg;3*^W-WYBK!OJAAU-%N9Mt_49ZzRWCquG}WPRkz@uPUllu
7586d2
jIzOMKFSg+CqdL=Mn!K`nb$RLf<M~V>L7{9Vwi5pX0LDXb
7586d2
7586d2
literal 0
7586d2
HcmV?d00001
7586d2
7586d2
-- 
7586d2
2.21.0
7586d2