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