From: "André Erdmann" <dywi@mailerd.de>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/R_overlay:master commit in: roverlay/ebuild/
Date: Thu, 25 Apr 2013 16:44:17 +0000 (UTC) [thread overview]
Message-ID: <1363536390.fd838576df5db122a01f3e2001577842db3575a3.dywi@gentoo> (raw)
commit: fd838576df5db122a01f3e2001577842db3575a3
Author: André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Sun Mar 17 14:02:15 2013 +0000
Commit: André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Sun Mar 17 16:06:30 2013 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=fd838576
ebuild/evars: make value strings more robust
This commit adds the following actions in order to protect against
undesirable side-effects:
* eliminate character sequences starting with "$("
* fix the value string of ListValues on a per-item basis
instead if editing the (final) ListValue string
* strip backslash chars at the end of value strings
---
roverlay/ebuild/abstractcomponents.py | 165 ++++++++++++++++++++++++---------
roverlay/ebuild/evars.py | 27 +++--
2 files changed, 136 insertions(+), 56 deletions(-)
diff --git a/roverlay/ebuild/abstractcomponents.py b/roverlay/ebuild/abstractcomponents.py
index 5b12260..b33189e 100644
--- a/roverlay/ebuild/abstractcomponents.py
+++ b/roverlay/ebuild/abstractcomponents.py
@@ -18,11 +18,68 @@ __all__ = [ 'ListValue', 'EbuildVar', ]
import re
+import roverlay.strutil
+
INDENT = '\t'
+# IGNORED_VALUE_CHARS
+# chars not allowed in value strings
+# Additionally, backslashes at the end of a string will be removed.
+IGNORED_VALUE_CHARS = "\"'`;"
+
+def _value_char_allowed ( c ):
+ """Returns True if the given char is allowed, else False (=char should
+ be ignored.
+
+ arguments:
+ * c --
+ """
+ return c not in IGNORED_VALUE_CHARS
+# --- end of _value_char_allowed (...) ---
+
+## IGNORED_VALUE_CODE, catches:
+## * command substitution: $(<cmd>), $(< <file>)
+## * arithmetic expansion: $((<statement>))
+##
+#IGNORED_VALUE_CODE = re.compile (
+# '[$][(]{1,2}[<]?(?P<text>.*?)[)]{1,2}\s*'
+#)
+
+# IGNORED_VALUE_CODE (strict), catches:
+# * any (sub)string beginning with '$(' which is either not allowed
+# or it leads to syntax errors
+#
+# This will remove more text than the variant above, but we cannot trust
+# that code injection always uses correct syntax.
+#
+IGNORED_VALUE_CODE = re.compile ( '[$][(].*' )
+
+def get_value_str ( value, quote_char=None ):
+ """Removes bad chars / substrings from vstr:
+ * non-ascii chars (this could be a no-op)
+ * IGNORED_VALUE_CHARS
+ * any substring starting with $(
+ * backslash characters at the end of the string
+
+ arguments:
+ * value --
+ """
+ s = IGNORED_VALUE_CODE.sub (
+ "",
+ roverlay.strutil.ascii_filter (
+ str ( value ), additional_filter=_value_char_allowed
+ )
+ ).rstrip ( "\\" )
+ if quote_char:
+ return quote_char + s + quote_char
+ else:
+ return s
+# --- end of get_value_str (...) ---
+
def listlike ( ref ):
"""Returns True if ref is listlike (a non-str iterable)."""
return hasattr ( ref, '__iter__' ) and not isinstance ( ref, str )
+# --- end of listlike (...) ---
class ListValue ( object ):
@@ -34,27 +91,27 @@ class ListValue ( object ):
arguments:
* value --
- * indent_level -- indention level ('\t') for extra value lines
+ * indent_level -- indention level ('\t') for value string lines
* empty_value -- if set: a string value that is always part
- of this ListValue's elements but ignored
- by len().
- Use cases are '${IUSE:-}' in the IUSE var etc.
+ of this ListValue's elements but ignored when
+ checking the number of stored items.
+ Use cases are '${IUSE:-}' in the IUSE var etc.
+ Defaults to None (which disables this feature).
+ * bash_array -- whether this value is a bash array or a string
+ Defaults to False.
"""
- self.set_level ( indent_level )
-
- self.empty_value = empty_value
-
-
+ self.empty_value = empty_value
self.single_line = False
self.indent_lines = True
- # only used in multi line mode
- self.append_indented_newline = True
-
self.is_bash_array = bash_array
self.insert_leading_newline = self.is_bash_array
- self.val_join = ' '
+ # only used when dealing with multi-line non-bash array values:
+ # append \n<var_indent> to the value string if True (useful for quoting
+ # such strings)
+ self.append_indented_newline = True
+ self.set_level ( indent_level )
self.set_value ( value )
# --- end of __init__ (...) ---
@@ -71,13 +128,14 @@ class ListValue ( object ):
def __len__ ( self ):
l = len ( self.value )
return max ( 0, l if self.empty_value is None else l - 1 )
+ # --- end of __len__ (...) ---
def set_level ( self, level ):
"""Sets the indention level."""
- self.level = level
- self.var_indent = (level - 1) * INDENT
- self.val_indent = level * INDENT
- self.line_join = '\n' + self.val_indent
+ self.level = level
+ self.var_indent = (level - 1) * INDENT
+ self.val_indent = level * INDENT
+ self.line_join_str = '\n' + self.val_indent
# --- end of set_level (...) ---
def set_value ( self, value ):
@@ -86,8 +144,7 @@ class ListValue ( object ):
if self.empty_value is not None:
self.value.append ( self.empty_value )
- if self._accept_value ( value ):
- self.add_value ( value )
+ self.add_value ( value )
# --- end of set_value (...) ---
def add ( self, value ):
@@ -105,54 +162,61 @@ class ListValue ( object ):
def to_str ( self ):
"""Returns a string representing this ListValue."""
+ def get_value_strings ( join_str, quoted=False ):
+ return join_str.join (
+ get_value_str (
+ v,
+ quote_char = "'" if quoted else None
+ ) for v in self.value
+ )
+ # --- end of get_value_strings (...) ---
+
value_count = len ( self.value )
+
if self.is_bash_array:
if value_count == 0:
# empty value
ret = "()"
- elif value_count == 1:
- # one value
- ret = "('" + str ( self.value [0] ) + "')"
- elif self.single_line:
- # several values in a single line
- ret = self.val_join.join ( self.value )
+
+ elif self.single_line or value_count == 1:
+ # one value or several values in a single line
+ ret = "( " + get_value_strings ( ' ', True ) + " )"
+
else:
- ret = "{intro}{values}{tail}{newline}".format (
- intro = '(\n' + self.val_indent \
- if self.insert_leading_newline else '( ',
- values = self.line_join.join (
- "'" + str ( x ) + "'" for x in self.value
+ ret = "{head}{values}{tail}".format (
+ head = (
+ ( '(\n' + self.val_indent )
+ if self.insert_leading_newline else '( '
),
- tail = '\n{indent})'.format ( indent=self.var_indent ),
- newline = self.var_indent + '\n' \
- if self.append_indented_newline else ''
+ values = get_value_strings ( self.line_join_str, True ),
+ tail = '\n' + self.var_indent + ')\n'
)
else:
if value_count == 0:
ret = ""
- elif value_count == 1:
- ret = str ( self.value [0] )
+ elif self.single_line or value_count == 1:
+ ret = get_value_strings ( ' ' )
else:
if self.insert_leading_newline:
ret = '\n' + self.val_indent
- ret += self.line_join.join ( ( self.value ) )
+ ret += get_value_strings ( self.line_join_str )
else:
- ret = self.line_join.join ( ( self.value ) )
+ ret = get_value_strings ( self.line_join_str )
if self.append_indented_newline:
- ret += self.var_indent + '\n'
+ ret += '\n' + self.var_indent
return ret
# --- end of to_str (...) ---
__str__ = to_str
+# --- end of ListValue ---
+
class EbuildVar ( object ):
"""An ebuild variable."""
- IGNORED_VALUE_CHARS = re.compile ( "[\"'`¸]" )
-
def __init__ ( self, name, value, priority, param_expansion=True ):
"""Initializes an EbuildVar.
@@ -199,11 +263,20 @@ class EbuildVar ( object ):
return True
# --- end of active (...) ---
- def _quote_value ( self ):
- if hasattr ( self, '_get_value_str' ):
- vstr = self._get_value_str()
+ def _get_value_str ( self ):
+ # hasattr ( ?? )
+ if isinstance ( self.value, ListValue ):
+ return self.value.to_str()
else:
- vstr = str ( self.value )
+ return get_value_str ( self.value )
+ # --- end of _get_value_str (...) ---
+
+ def _quote_value ( self ):
+ vstr = self._get_value_str()
+
+ if hasattr ( self, '_transform_value_str' ):
+ vstr = self._transform_value_str ( vstr )
+ # -- end if
if self.use_param_expansion is None:
# value quoting / unquoting is disabled
@@ -217,7 +290,7 @@ class EbuildVar ( object ):
if len ( vstr ) == 0:
return 2 * q
else:
- return q + EbuildVar.IGNORED_VALUE_CHARS.sub ( '', vstr ) + q
+ return q + vstr + q
# --- end of _quote_value (...) ---
def __str__ ( self ):
@@ -233,3 +306,5 @@ class EbuildVar ( object ):
# contain only quote chars
return self._empty_str() if hasattr ( self, '_empty_str' ) else ""
# --- end of __str__ (...) ---
+
+# --- end of EbuildVar ---
diff --git a/roverlay/ebuild/evars.py b/roverlay/ebuild/evars.py
index cb3ec17..cd8becb 100644
--- a/roverlay/ebuild/evars.py
+++ b/roverlay/ebuild/evars.py
@@ -17,39 +17,44 @@ __all__ = [ 'DEPEND', 'DESCRIPTION', 'IUSE', 'MISSINGDEPS',
'RDEPEND', 'R_SUGGESTS', 'SRC_URI', 'KEYWORDS',
]
-from roverlay import strutil
+import roverlay.strutil
from roverlay.ebuild.abstractcomponents import ListValue, EbuildVar
IUSE_SUGGESTS = 'R_suggests'
RSUGGESTS_NAME = IUSE_SUGGESTS.upper()
-SEE_METADATA = '... (see metadata)'
-
-# ignoring case policies here (camel case,..)
+# ignoring style guide here (camel case, ...)
class DESCRIPTION ( EbuildVar ):
"""A DESCRIPTION="..." statement."""
- def __init__ ( self, description, maxlen=50 ):
+
+ SEE_METADATA = '... (see metadata)'
+
+ def __init__ ( self, description, maxlen=None ):
"""A DESCRIPTION="..." statement. Long values will be truncated.
arguments:
* description -- description text
- * maxlen -- maximum value length (defaults to 50 chars)
+ * maxlen -- maximum value length (>0, defaults to 50 chars)
"""
+ assert maxlen is None or maxlen > 0
+
super ( DESCRIPTION, self ) . __init__ (
name='DESCRIPTION',
value=description,
priority=80, param_expansion=False
)
- self.maxlen = 50 if maxlen is None else maxlen
+ self.maxlen = maxlen or 50
# --- end of __init__ (...) ---
- def _get_value_str ( self ):
- return strutil.shorten_str (
- strutil.ascii_filter ( str ( self.value ) ), self.maxlen, SEE_METADATA
+ def _transform_value_str ( self, _str ):
+ return roverlay.strutil.shorten_str (
+ _str,
+ self.maxlen,
+ self.SEE_METADATA
)
- # --- end of _get_value_str (...) ---
+ # --- end of _transform_value_str (...) ---
class KEYWORDS ( EbuildVar ):
next reply other threads:[~2013-04-25 16:44 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-25 16:44 André Erdmann [this message]
-- strict thread matches above, loose matches on Subject: below --
2023-08-01 3:38 [gentoo-commits] proj/R_overlay:master commit in: roverlay/ebuild/ Benda XU
2019-08-17 16:41 Benda XU
2013-09-05 15:43 André Erdmann
2013-08-28 9:38 André Erdmann
2013-08-23 13:52 André Erdmann
2013-07-29 8:55 André Erdmann
2013-07-25 16:39 André Erdmann
2013-07-25 13:25 André Erdmann
2013-07-25 8:06 André Erdmann
2013-07-25 8:06 André Erdmann
2013-07-10 16:16 André Erdmann
2013-07-10 8:26 [gentoo-commits] proj/R_overlay:gsoc13/next " André Erdmann
2013-07-10 16:16 ` [gentoo-commits] proj/R_overlay:master " André Erdmann
2013-06-19 18:58 [gentoo-commits] proj/R_overlay:gsoc13/next " André Erdmann
2013-06-19 18:59 ` [gentoo-commits] proj/R_overlay:master " André Erdmann
2013-06-05 18:08 [gentoo-commits] proj/R_overlay:gsoc13/next " André Erdmann
2013-06-13 16:34 ` [gentoo-commits] proj/R_overlay:master " André Erdmann
2013-04-25 16:44 André Erdmann
2013-01-30 20:16 André Erdmann
2013-01-30 20:16 André Erdmann
2013-01-30 20:16 André Erdmann
2013-01-30 20:16 André Erdmann
2012-08-09 9:26 André Erdmann
2012-08-07 8:50 André Erdmann
2012-08-03 13:38 André Erdmann
2012-08-03 13:38 André Erdmann
2012-08-02 15:14 André Erdmann
2012-08-02 15:14 André Erdmann
2012-07-30 8:52 [gentoo-commits] proj/R_overlay:overlay_wip " André Erdmann
2012-07-30 8:52 ` [gentoo-commits] proj/R_overlay:master " André Erdmann
2012-07-16 16:15 André Erdmann
2012-07-16 16:15 André Erdmann
2012-07-12 18:04 André Erdmann
2012-07-06 22:19 André Erdmann
2012-06-29 22:48 André Erdmann
2012-06-29 22:48 André Erdmann
2012-06-29 22:48 André Erdmann
2012-06-29 22:48 André Erdmann
2012-06-28 15:55 André Erdmann
2012-06-28 13:29 André Erdmann
2012-06-26 15:42 André Erdmann
2012-06-21 16:55 André Erdmann
2012-06-20 19:03 André Erdmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1363536390.fd838576df5db122a01f3e2001577842db3575a3.dywi@gentoo \
--to=dywi@mailerd.de \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox