Skip to content

Length Validator Broken when min=0 #872

Open
@jb2170

Description

@jb2170

PR incoming.

Actual Behavior

WTForm's Length validator incorrectly approves a missing string (aka field.data is None) when min=0, whereas it should fail validation.

I interpret min=-1 to mean 'no minimum length, permit None and the empty string '''

I interpret min=0 to mean 'minimum length 0, do not permit None, aka a missing field, but do permit the empty string '''

Serving the following app with $ gunicorn min-len-fail:app on the default localhost:8000

from flask              import Flask, request, jsonify
from wtforms            import Form, StringField
from wtforms.validators import Length

app = Flask(__name__)

class TestForm(Form):
    title = StringField("Title", validators = [Length(min=0)])

@app.route("/", methods = ["POST"])
def index():
    form = TestForm(request.form)
    if form.validate():
        return jsonify({"msg": "Success!", "title": form.title.data})
    else:
        return jsonify(form.errors), 400

Test POSTing title both as missing, and as the empty string, with curl

$ curl -sSL -d 'titl=' localhost:8000
{"msg":"Success!","title":null}
$ curl -sSL -d 'title=' localhost:8000
{"msg":"Success!","title":""}

The Length validator reports success for both cases, whereas it should fail the first.

Expected Behavior

With the PR incoming

$ curl -sSL -d 'titl=' localhost:8000
{"title":["Field must be at least 0 characters long."]}
$ curl -sSL -d 'title=' localhost:8000
{"msg":"Success!","title":""}

Environment

  • Python version: 3.12.7, Arch Linux
  • wtforms version: main branch (3.2.1)

Cause

class Length:
    ...
    def __call__(self, form, field):
        length = field.data and len(field.data) or 0
        ...

The default length of 0 is incorrect; it should be -1. And no we can't just change the 0 to a -1 in that awful x and y or z mess otherwise the empty string would incorrectly set length to -1.

I've added three tests for the Length validator to stress-test the difference between the None missing string and the '' empty string.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions