encode / django-rest-framework

Web APIs for Django. 🎸
https://www.django-rest-framework.org
Other
28.47k stars 6.85k forks source link

Unexpected serializers.UUIDField behaviour #9555

Open raqsilva8 opened 1 month ago

raqsilva8 commented 1 month ago

The issue

When the serializer receives a UUID that we might think is invalid, it gets "cleaned" up and considered valid, returning a completely different UUID.

How to replicate

from django.test import TestCase
from rest_framework import serializers

class TestSerializer(serializers.Serializer):
    uuid = serializers.UUIDField(format='hex_verbose')

class SerializerTest(TestCase):
    def test_serializer(self):
        self.assertTrue(TestSerializer(data={'uuid': '524e802a-061a-4778-b2f9-f5d3d7afd581'}).is_valid())
        serializer = TestSerializer(data={'uuid': '524e802_061a-4778-b2f9-f5d3d7afd581'})
        self.assertTrue(serializer.is_valid())
        self.assertEqual(str(serializer.validated_data['uuid']), '0524e802-061a-4778-b2f9-f5d3d7afd581')
        self.assertFalse(TestSerializer(data={'uuid': '524e802a_061a-4778-b2f9-f5d3d7afd581'}).is_valid())

A simple way to replicate is to actually use the uuid package:

import uuid
assert str(uuid.UUID(hex="524e802_061a-4778-b2f9-f5d3d7afd581")) == "0524e802-061a-4778-b2f9-f5d3d7afd581"

Note the differences 524e802_061a and 0524e802-061a

sevdog commented 1 month ago

This is not a bug of DRF, it is a Python standardlib bug https://github.com/python/cpython/issues/125651, the fact that you can provide an underscore to UUID constructor means that it is accepting invalid values.