huggingface / huggingface/datasets
ClassLabel.str2int and int2str do not validate the elements of an iterable
- Dominant language
- Python
- Stars
- 22k
- Forks
- 3.4k
- Avg merge
- 5d 7h
- Merged PRs (30d)
- 17
Description
### Describe the bug
`ClassLabel.str2int` and `ClassLabel.int2str` both validate the *container* they're given, but never the elements inside it. Two of the resulting cases fail silently and return wrong labels rather than raising.
`str2int` accepts ints and hands them straight back, so a column of integer labels round-trips through a "string to int" call untouched instead of being rejected:
```python
>>> from datasets import ClassLabel
>>> cl = ClassLabel(names=["neg", "pos"])
>>> cl.str2int([1])
[1]
>>> cl.str2int([5]) # not even a valid class id
[5]
```
`int2str` truncates floats through `int(v)`, so a float silently resolves to a label:
```python
>>> cl.int2str([1.7])
['pos']
```
The remaining two are loud but misleading. A nested string still produces the cryptic `TypeError` that #8416 is fixing at the top level:
```python
>>> cl.int2str(["1"])
TypeError: '<=' not supported between instances of 'int' and 'str'
```
and `bytes` gets iterated into its byte values:
```python
>>> cl.int2str(b"1")
ValueError: Invalid integer class label 49 # 49 is ord("1")
```
### Cause
Both methods guard only the argument itself:
```python
if not isinstance(values, int) and not isinstance(values, Iterable):
raise ValueError(...)
```
after which `int2str` does `if not 0 <= v < self.num_classes` (which is what raises the `TypeError` on a str element, and what a float passes) and `str2int`'s loop only checks membership for values it recognises as strings, letting anything else fall through to the return.
#8416 tightens the top-level check for `str`, which fixes `int2str("1")` but not `int2str(["1"])`, and doesn't address the two silent cases at all.
### Expected behavior
Every element is validated, so all four raise a `ValueError` naming the offending value — in particular `str2int([1])` and `int2str([1.7])` should not return a result.
`str2int([1])` returning `[1]` is the one I'd flag as most worth fixing: it's silent, and it means a mistakenly-already-encoded label column survives a `str2int` call looking like it was encoded correctly.
### Environment info
- `datasets` 4.5.1.dev0 (main @ 48b7ee7)
- Python 3.11.9, Windows
I'm happy to open a PR adding per-element validation to both methods if you'd like it — it would want coordinating with #8416 since they touch the same guard.
Contributor guide
Research direction
Start by locating the ClassLabel.str2int and ClassLabel.int2str entry points and read their iterable handling. Check how each method currently validates values, including the cases described in the issue and the related #8416 change. Done means every iterable element is validated and invalid values raise ValueError without silently passing through or being truncated.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- data
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 68/100