def read_frames(id3, data, frames):
    """Does not error out"""

    assert id3.version >= ID3Header._V22

    result = []
    unsupported_frames = []

    if id3.version < ID3Header._V24 and id3.f_unsynch:
        try:
            data = unsynch.decode(data)
        except ValueError:
            pass

    if id3.version >= ID3Header._V23:
        if id3.version < ID3Header._V24:
            bpi = int
        else:
            bpi = determine_bpi(data, frames)

        while data:
            header = data[:10]
            try:
                name, size, flags = struct.unpack('>4sLH', header)
            except struct.error:
                break  # not enough header
            if name.strip(b'\x00') == b'':
                break

            size = bpi(size)
            framedata = data[10:10 + size]
            data = data[10 + size:]
            if size == 0:
                continue  # drop empty frames

            if PY3:
                try:
                    name = name.decode('ascii')
                except UnicodeDecodeError:
                    continue

            try:
                # someone writes 2.3 frames with 2.2 names
                if name[-1] == "\x00":
                    tag = Frames_2_2[name[:-1]]
                    name = tag.__base__.__name__

                tag = frames[name]
            except KeyError:
                if is_valid_frame_id(name):
                    unsupported_frames.append(header + framedata)
            else:
                try:
                    result.append(tag._fromData(id3, flags, framedata))
                except NotImplementedError:
                    unsupported_frames.append(header + framedata)
                except ID3JunkFrameError:
                    pass
    elif id3.version >= ID3Header._V22:
        while data:
            header = data[0:6]
            try:
                name, size = struct.unpack('>3s3s', header)
            except struct.error:
                break  # not enough header
            size, = struct.unpack('>L', b'\x00' + size)
            if name.strip(b'\x00') == b'':
                break

            framedata = data[6:6 + size]
            data = data[6 + size:]
            if size == 0:
                continue  # drop empty frames

            if PY3:
                try:
                    name = name.decode('ascii')
                except UnicodeDecodeError:
                    continue

            try:
                tag = frames[name]
            except KeyError:
                if is_valid_frame_id(name):
                    unsupported_frames.append(header + framedata)
            else:
                try:
                    result.append(
                        tag._fromData(id3, 0, framedata))
                except (ID3EncryptionUnsupportedError,
                        NotImplementedError):
                    unsupported_frames.append(header + framedata)
                except ID3JunkFrameError:
                    pass

    return result, unsupported_frames, data
Does not error out