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