# Path: keepkeylib/tools.py
# def parse_path(nstr):
#     """
#     Convert BIP32 path string to list of uint32 integers with hardened flags.
#     Several conventions are supported to set the hardened flag: -1, 1', 1h
#     e.g.: "0/1h/1" -> [0, 0x80000001, 1]
#     :param nstr: path string
#     :return: list of integers
#     """
#     if not nstr:
#         return []
# 
#     n = nstr.split('/')
# 
#     # m/a/b/c => a/b/c
#     if n[0] == 'm':
#         n = n[1:]
# 
#     # coin_name/a/b/c => 44'/SLIP44_constant'/a/b/c
#     #if n[0] in slip44:
#     #    coin_id = slip44[n[0]]
#     #    n[0:1] = ['44h', '{}h'.format(coin_id)]
# 
#     def str_to_harden(x):
#         if x.startswith('-'):
#             return H_(abs(int(x)))
#         elif x.endswith(('h', "'")):
#             return H_(int(x[:-1]))
#         else:
#             return int(x)
# 
#     try:
#         return list(str_to_harden(x) for x in n)
#     except Exception:
#         raise ValueError('Invalid BIP32 path', nstr)


import unittest
import common
from keepkeylib import messages_pb2 as proto
from keepkeylib import types_pb2 as proto_types
from keepkeylib.tools import parse_path
            # Send final ack
            self.assertIsInstance(ret, proto.CharacterRequest)
            ret = self.client.call_raw(proto.CharacterAck(done=True))

            # Workflow succesfully ended
            self.assertIsInstance(ret, proto.Success)

            self.client.init_device()
            self.assertEqual(self.client.debug.read_mnemonic(), mnemonic)

            # wipe device
            ret = self.client.call_raw(proto.WipeDevice())
            self.client.debug.press_yes()
            ret = self.client.call_raw(proto.ButtonAck())

    def test_vuln1971(self):
        self.setup_mnemonic_allallall()

        self.assertEqual(self.client.get_address("Testnet", parse_path("49'/1'/0'/1/0"), True, None, script_type=proto_types.SPENDP2SHWITNESS), '2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX')

        # Previously, there weren't good checks on the expected state of the
        # recovery cipher state machine, which led to this case triggering an
        # out of bounds memory access, as well as setting the device's mnemonic
        # to "".
        self.client.call_raw(proto.CharacterAck(done=True))

        # The emulator, with ASan enabled, crashes on the out of bounds
        # memory access before even getting to the part where the empty
        # mnemonic is pushed into storage, but for posterity, let's make sure
        # we still get the correct address afterward:

# Path: keepkeylib/tools.py
# def parse_path(nstr):
#     """
#     Convert BIP32 path string to list of uint32 integers with hardened flags.
#     Several conventions are supported to set the hardened flag: -1, 1', 1h
#     e.g.: "0/1h/1" -> [0, 0x80000001, 1]
#     :param nstr: path string
#     :return: list of integers
#     """
#     if not nstr:
#         return []
# 
#     n = nstr.split('/')
# 
#     # m/a/b/c => a/b/c
#     if n[0] == 'm':
#         n = n[1:]
# 
#     # coin_name/a/b/c => 44'/SLIP44_constant'/a/b/c
#     #if n[0] in slip44:
#     #    coin_id = slip44[n[0]]
#     #    n[0:1] = ['44h', '{}h'.format(coin_id)]
# 
#     def str_to_harden(x):
#         if x.startswith('-'):
#             return H_(abs(int(x)))
#         elif x.endswith(('h', "'")):
#             return H_(int(x[:-1]))
#         else:
#             return int(x)
# 
#     try:
#         return list(str_to_harden(x) for x in n)
#     except Exception:
#         raise ValueError('Invalid BIP32 path', nstr)


# Path: tests/test_msg_recoverydevice_cipher.py
import unittest
import common
from keepkeylib import messages_pb2 as proto
from keepkeylib import types_pb2 as proto_types
from keepkeylib.tools import parse_path

            # Send final ack
            self.assertIsInstance(ret, proto.CharacterRequest)
            ret = self.client.call_raw(proto.CharacterAck(done=True))

            # Workflow succesfully ended
            self.assertIsInstance(ret, proto.Success)

            self.client.init_device()
            self.assertEqual(self.client.debug.read_mnemonic(), mnemonic)

            # wipe device
            ret = self.client.call_raw(proto.WipeDevice())
            self.client.debug.press_yes()
            ret = self.client.call_raw(proto.ButtonAck())

    def test_vuln1971(self):
        self.setup_mnemonic_allallall()

        self.assertEqual(self.client.get_address("Testnet", parse_path("49'/1'/0'/1/0"), True, None, script_type=proto_types.SPENDP2SHWITNESS), '2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX')

        # Previously, there weren't good checks on the expected state of the
        # recovery cipher state machine, which led to this case triggering an
        # out of bounds memory access, as well as setting the device's mnemonic
        # to "".
        self.client.call_raw(proto.CharacterAck(done=True))

        # The emulator, with ASan enabled, crashes on the out of bounds
        # memory access before even getting to the part where the empty
        # mnemonic is pushed into storage, but for posterity, let's make sure
        # we still get the correct address afterward:

        self.assertEqual(self.client.get_address("Testnet", parse_path("49'/1'/0'/1/0"), True, None, script_type=proto_types.SPENDP2SHWITNESS), '2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX')