Repository: pydicom/pydicom

Issue:
OverflowError "VR of 'DS' must be <= 16 characters long" triggered when element is 16 characters long
**Describe the bug**

`OverflowError` triggered while accessing `PixelData`, which the values compliant with the standard. In the sample referenced in the example below, we have this, which satisfies DS VR:

```
(0028,0030) DS [.002006091181818\.002006091181818]      #  34, 2 PixelSpacing
```

But nevertheless the error is triggered while trying to access `PixelData`:

```
OverflowError: Values for elements with a VR of 'DS' must be <= 16 characters long, 
but the float provided requires > 16 characters to be accurately represented. Use a 
smaller string, set 'config.settings.reading_validation_mode' to 'WARN' to override 
the length check, or explicitly construct a DS object with 'auto_format' set to True
```

**Expected behavior**

`OverflowError` does not get triggered.

**Steps To Reproduce**

Follow the steps of this Colab notebook: https://colab.research.google.com/drive/1FcSgjBKazh0YN-jlJYdID0YUTh90CAvZ?usp=sharing

**Your environment**

```
module       | version
------       | -------
platform     | Linux-5.4.144+-x86_64-with-Ubuntu-18.04-bionic
Python       | 3.7.13 (default, Mar 16 2022, 17:37:17)  [GCC 7.5.0]
pydicom      | 2.3.0
gdcm         | _module not found_
jpeg_ls      | _module not found_
numpy        | 1.21.5
PIL          | 9.1.0
pylibjpeg    | _module not found_
openjpeg     | _module not found_
libjpeg      | _module not found_
```

Related issue: https://github.com/imi-bigpicture/wsidicom/issues/49

cc: @DanielaSchacherer @dclunie @hackermd 

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/pydicom/pydicom/pull/1633?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) Report
> Merging [#1633](https://codecov.io/gh/pydicom/pydicom/pull/1633?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) (77fd9bd) into [master](https://codecov.io/gh/pydicom/pydicom/commit/37c0f957dcadebc93e6572a338e06150f7397732?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) (37c0f95) will **decrease** coverage by `9.52%`.
> The diff coverage is `100.00%`.

```diff
@@            Coverage Diff             @@
##           master    #1633      +/-   ##
==========================================
- Coverage   97.57%   88.04%   -9.53%     
==========================================
  Files          66       66              
  Lines       10660    10419     -241     
==========================================
- Hits        10401     9173    -1228     
- Misses        259     1246     +987     
```


| [Impacted Files](https://codecov.io/gh/pydicom/pydicom/pull/1633?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) | Coverage Δ | |
|---|---|---|
| [pydicom/valuerep.py](https://codecov.io/gh/pydicom/pydicom/pull/1633/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS92YWx1ZXJlcC5weQ==) | `99.37% <100.00%> (ø)` | |
| [pydicom/pixel\_data\_handlers/util.py](https://codecov.io/gh/pydicom/pydicom/pull/1633/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9waXhlbF9kYXRhX2hhbmRsZXJzL3V0aWwucHk=) | `17.93% <0.00%> (-82.07%)` | :arrow_down: |
| [pydicom/waveforms/numpy\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1633/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS93YXZlZm9ybXMvbnVtcHlfaGFuZGxlci5weQ==) | `20.31% <0.00%> (-79.69%)` | :arrow_down: |
| [pydicom/encoders/gdcm.py](https://codecov.io/gh/pydicom/pydicom/pull/1633/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9lbmNvZGVycy9nZGNtLnB5) | `20.96% <0.00%> (-75.81%)` | :arrow_down: |
| [pydicom/pixel\_data\_handlers/numpy\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1633/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9waXhlbF9kYXRhX2hhbmRsZXJzL251bXB5X2hhbmRsZXIucHk=) | `27.14% <0.00%> (-72.86%)` | :arrow_down: |
| [pydicom/pixel\_data\_handlers/gdcm\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1633/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9waXhlbF9kYXRhX2hhbmRsZXJzL2dkY21faGFuZGxlci5weQ==) | `26.22% <0.00%> (-66.46%)` | :arrow_down: |
| [pydicom/overlays/numpy\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1633/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9vdmVybGF5cy9udW1weV9oYW5kbGVyLnB5) | `35.18% <0.00%> (-64.82%)` | :arrow_down: |
| [pydicom/pixel\_data\_handlers/pillow\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1633/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9waXhlbF9kYXRhX2hhbmRsZXJzL3BpbGxvd19oYW5kbGVyLnB5) | `31.73% <0.00%> (-64.43%)` | :arrow_down: |
| [pydicom/pixel\_data\_handlers/rle\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1633/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9waXhlbF9kYXRhX2hhbmRsZXJzL3JsZV9oYW5kbGVyLnB5) | `36.44% <0.00%> (-63.56%)` | :arrow_down: |
| [pydicom/pixel\_data\_handlers/pylibjpeg\_handler.py](https://codecov.io/gh/pydicom/pydicom/pull/1633/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom#diff-cHlkaWNvbS9waXhlbF9kYXRhX2hhbmRsZXJzL3B5bGlianBlZ19oYW5kbGVyLnB5) | `40.74% <0.00%> (-57.41%)` | :arrow_down: |
| ... and [18 more](https://codecov.io/gh/pydicom/pydicom/pull/1633/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom) | |

:mega: Codecov can now indicate which changes are the most critical in Pull Requests. [Learn more](https://about.codecov.io/product/feature/runtime-insights/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pydicom)


Patch:
diff --git a/doc/release_notes/v2.4.0.rst b/doc/release_notes/v2.4.0.rst
index 33b70f399..bb50bf9b2 100644
--- a/doc/release_notes/v2.4.0.rst
+++ b/doc/release_notes/v2.4.0.rst
@@ -4,4 +4,10 @@ Version 2.4.0
 Enhancements
 ------------
 * Added attribute :attr:`~pydicom.valuerep.PersonName.alphabetic` (:pr:`1634`)
+
+Fixes
+-----
+* Fixed length validation of DS values with maximum length without a leading
+  zero (:issue:`1632`)
 * Increased download speed with progress bar for test data (:issue:`1611`)
+
diff --git a/pydicom/valuerep.py b/pydicom/valuerep.py
index 735671323..598a8a4c6 100644
--- a/pydicom/valuerep.py
+++ b/pydicom/valuerep.py
@@ -874,7 +874,7 @@ class DSfloat(float):
 
         if (validation_mode == config.RAISE and
                 not self.auto_format):
-            if len(repr(self)[1:-1]) > 16:
+            if len(str(self)) > 16:
                 raise OverflowError(
                     "Values for elements with a VR of 'DS' must be <= 16 "
                     "characters long, but the float provided requires > 16 "
@@ -884,7 +884,7 @@ class DSfloat(float):
                     "explicitly construct a DS object with 'auto_format' "
                     "set to True"
                 )
-            if not is_valid_ds(repr(self)[1:-1]):
+            if not is_valid_ds(str(self)):
                 # This will catch nan and inf
                 raise ValueError(
                     f'Value "{str(self)}" is not valid for elements with a VR '


Test patch:
diff --git a/pydicom/tests/test_valuerep.py b/pydicom/tests/test_valuerep.py
index fee39b80d..75286600f 100644
--- a/pydicom/tests/test_valuerep.py
+++ b/pydicom/tests/test_valuerep.py
@@ -603,6 +603,13 @@ class TestDSfloat:
             valuerep.DSfloat('3.141592653589793',
                              validation_mode=config.RAISE)
 
+    def test_handle_missing_leading_zero(self):
+        """Test that no error is raised with maximum length DS string
+        without leading zero."""
+        # Regression test for #1632
+        valuerep.DSfloat(".002006091181818",
+                         validation_mode=config.RAISE)
+
     def test_DSfloat_auto_format(self):
         """Test creating a value using DSfloat copies auto_format"""
         x = DSfloat(math.pi, auto_format=True)