diff test/db_test_base.py @ 8268:05d8806b25ad

fix: issue2551387 - TypeError: not indexable. Fix crash due to uninitialized list element on a (Mini)FieldStorage when unexpected input is posted via wsgi. This doesn't happen when running roundup-server. It might happen under other front ends. Moved the code that sets '.list = [] if .list == None' to the main flow. Added an exception hander that logs the value of self.form if self.form.list raises an AttributeError. This exception should never happen if I understand the code correctly (but I probably don't). Fixed a number of test cases that were broken because I was calling Client and passing '[]' rather than a cgi.formStorage object. Added test cases: create a FileStorage (self.form) with .list = None. check AttributeError exception and verify logging. Problem reported and debugged by Christof Meerwald.
author John Rouillard <rouilj@ieee.org>
date Sun, 12 Jan 2025 12:34:52 -0500
parents 741ea8a86012
children 7a7f6ee0a09e
line wrap: on
line diff
--- a/test/db_test_base.py	Thu Jan 09 10:14:55 2025 -0500
+++ b/test/db_test_base.py	Sun Jan 12 12:34:52 2025 -0500
@@ -30,6 +30,14 @@
 from email import message_from_string
 
 import pytest
+
+try:
+    from StringIO import cStringIO as IOBuff
+except ImportError:
+    # python 3
+    from io import BytesIO as IOBuff
+
+from roundup.cgi.client import BinaryFieldStorage
 from roundup.hyperdb import String, Password, Link, Multilink, Date, \
     Interval, DatabaseError, Boolean, Number, Node, Integer
 from roundup.mailer import Mailer
@@ -43,7 +51,7 @@
 from roundup.exceptions import UsageError, Reject
 from roundup.mlink_expr import ExpressionError
 
-from roundup.anypy.strings import b2s, s2b, u2s
+from roundup.anypy.strings import b2s, bs2b, s2b, u2s
 from roundup.anypy.cmp_ import NoneAndDictComparable
 from roundup.anypy.email_ import message_from_bytes
 
@@ -4340,6 +4348,14 @@
         ae(bool(issue ['priority']['name']),False)
 
 def makeForm(args):
+    """ Takes a dict of form elements or a FieldStorage.
+
+         FieldStorage is just returned so you can pass the result from
+         makeFormFromString through it cleanly.
+    """
+    if isinstance(args, cgi.FieldStorage):
+        return args
+
     form = cgi.FieldStorage()
     for k,v in args.items():
         if type(v) is type([]):
@@ -4352,6 +4368,33 @@
             form.list.append(cgi.MiniFieldStorage(k, v))
     return form
 
+def makeFormFromString(bstring, env=None):
+    """used for generating a form that looks like a rest or xmlrpc
+       payload. Takes a binary or regular string and stores
+       it in a FieldStorage object.
+
+       :param: bstring - binary or regular string
+       :param" env - dict of environment variables. Names/keys
+               must be uppercase.
+                  e.g. {"REQUEST_METHOD": "DELETE"}
+
+       Ideally this would be part of makeForm, but the env dict
+       is needed here to allow FieldStorage to properly define
+       the resulting object.
+    """
+    rfile=IOBuff(bs2b(bstring))
+
+    # base headers required for BinaryFieldStorage/FieldStorage
+    e = {'REQUEST_METHOD':'POST',
+         'CONTENT_TYPE': 'text/xml',
+         'CONTENT_LENGTH': str(len(bs2b(bstring)))
+         }
+    if env:
+        e.update(env)
+
+    form = BinaryFieldStorage(fp=rfile, environ=e)
+    return form
+
 class FileUpload:
     def __init__(self, content, filename):
         self.content = content

Roundup Issue Tracker: http://roundup-tracker.org/