prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [BUG] Possibly unsafe conversion of DatasetDiff instance to bytes
  ## 🐛🐛 Bug Report
  
  ### ⚗️ Current Behavior
  
  The code block
  
  https://github.com/activeloopai/deeplake/blob/c88925d8afa94841972fe4fd6f1ddeb1ede8dde0/deeplake/core/version_control/dataset_diff.py#L37-L39
  
  assumes `len(str.encode('utf-8')) == len(str)` which is not true in general.
  
  ### 🧰 Possible Solution
  
  The code block should read:
  ```python
                              len(old_name_encoded).to_bytes(8, "big"),
                              len(new_name_encoded).to_bytes(8, "big"),
                              old_name_encoded + new_name_encoded,
  ```
  where
  ```python
  old_name_encoded = old_name.encode("utf-8")
  new_name_encoded = new_name.encode("utf-8")
  ```
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `deeplake/core/version_control/dataset_diff.py`
  Content:
  ```
  1 from deeplake.core.storage.deeplake_memory_object import DeepLakeMemoryObject
  2 from deeplake.core.storage import LRUCache
  3 from deeplake.util.keys import get_dataset_diff_key
  4 import typing
  5 from collections import OrderedDict
  6 
  7 
  8 class DatasetDiff(DeepLakeMemoryObject):
  9     def __init__(self) -> None:
  10         self.is_dirty = False
  11         self.info_updated = False
  12         self.renamed: typing.OrderedDict = OrderedDict()
  13         self.deleted: typing.List[str] = []
  14 
  15     def tobytes(self) -> bytes:
  16         """Returns bytes representation of the dataset diff
  17 
  18         The format stores the following information in order:
  19         1. The first byte is a boolean value indicating whether the Dataset info was modified or not.
  20         2. The next 8 bytes give the number of renamed tensors, let's call this m.
  21         3. Next, there will be m blocks of bytes with the following format:
  22             1. 8 + 8 bytes giving the length of old and new names, let's call them x and y.
  23             2. x bytes of old name.
  24             3. y bytes of new name.
  25         4. The next 8 bytes give the number of deleted tensors, let's call this n.
  26         5. Next, there will be n blocks of bytes with the following format:
  27             1. 8 bytes giving the length of the name of the deleted tensor, let's call this z.
  28             2. n bytes of name of the deleted tensor.
  29         """
  30         return b"".join(
  31             [
  32                 self.info_updated.to_bytes(1, "big"),
  33                 len(self.renamed).to_bytes(8, "big"),
  34                 *(
  35                     b"".join(
  36                         [
  37                             len(old_name).to_bytes(8, "big"),
  38                             len(new_name).to_bytes(8, "big"),
  39                             (old_name + new_name).encode("utf-8"),
  40                         ]
  41                     )
  42                     for old_name, new_name in self.renamed.items()
  43                 ),
  44                 len(self.deleted).to_bytes(8, "big"),
  45                 *(
  46                     b"".join([len(name).to_bytes(8, "big"), name.encode("utf-8")])
  47                     for name in self.deleted
  48                 ),
  49             ]
  50         )
  51 
  52     @classmethod
  53     def frombuffer(cls, data: bytes) -> "DatasetDiff":
  54         """Creates a DatasetDiff object from bytes"""
  55         dataset_diff = cls()
  56         dataset_diff.info_updated = bool(int.from_bytes(data[:1], "big"))
  57         len_renamed = int.from_bytes(data[1:9], "big")
  58         pos = 9
  59         for _ in range(len_renamed):
  60             len_old, len_new = (
  61                 int.from_bytes(data[pos : pos + 8], "big"),
  62                 int.from_bytes(data[pos + 8 : pos + 16], "big"),
  63             )
  64             pos += 16
  65             old_name, new_name = (
  66                 data[pos : pos + len_old].decode("utf-8"),
  67                 data[pos + len_old : pos + len_old + len_new].decode("utf-8"),
  68             )
  69             pos += len_old + len_new
  70             dataset_diff.renamed[old_name] = new_name
  71         len_deleted = int.from_bytes(data[pos : pos + 8], "big")
  72         pos += 8
  73         for _ in range(len_deleted):
  74             len_name = int.from_bytes(data[pos : pos + 8], "big")
  75             pos += 8
  76             name = data[pos : pos + len_name].decode("utf-8")
  77             pos += len_name
  78             dataset_diff.deleted.append(name)
  79         return dataset_diff
  80 
  81     @property
  82     def nbytes(self):
  83         """Returns number of bytes required to store the dataset diff"""
  84         return 1
  85 
  86     def modify_info(self) -> None:
  87         """Stores information that the info has changed"""
  88         self.info_updated = True
  89         self.is_dirty = True
  90 
  91     def tensor_renamed(self, old_name, new_name):
  92         """Adds old and new name of a tensor that was renamed to renamed"""
  93         for old, new in self.renamed.items():
  94             if old_name == new:
  95                 if old == new_name:
  96                     self.renamed.pop(old)
  97                 else:
  98                     self.renamed[old] = new_name
  99                 break
  100         else:
  101             self.renamed[old_name] = new_name
  102 
  103         self.is_dirty = True
  104 
  105     def tensor_deleted(self, name):
  106         """Adds name of deleted tensor to deleted"""
  107         if name not in self.deleted:
  108             for old, new in self.renamed.items():
  109                 if name == new:
  110                     self.renamed.pop(old)
  111                     self.deleted.append(old)
  112                     break
  113             else:
  114                 self.deleted.append(name)
  115             self.is_dirty = True
  116 
  117 
  118 def load_dataset_diff(dataset):
  119     storage: LRUCache = dataset.storage
  120     path = get_dataset_diff_key(dataset.version_state["commit_id"])
  121     try:
  122         diff = storage.get_deeplake_object(path, DatasetDiff)
  123     except KeyError:
  124         diff = DatasetDiff()
  125     storage.register_deeplake_object(path, diff)
  126     return diff
  127
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/deeplake/core/version_control/dataset_diff.py b/deeplake/core/version_control/dataset_diff.py
  --- a/deeplake/core/version_control/dataset_diff.py
  +++ b/deeplake/core/version_control/dataset_diff.py
  @@ -36,10 +36,13 @@
                           [
                               len(old_name).to_bytes(8, "big"),
                               len(new_name).to_bytes(8, "big"),
  -                            (old_name + new_name).encode("utf-8"),
  +                            (old_name + new_name),
                           ]
                       )
  -                    for old_name, new_name in self.renamed.items()
  +                    for old_name, new_name in map(
  +                        lambda n: (n[0].encode("utf-8"), n[1].encode("utf-8")),
  +                        self.renamed.items(),
  +                    )
                   ),
                   len(self.deleted).to_bytes(8, "big"),
                   *(
  
verification_info: {"golden_diff": "diff --git a/deeplake/core/version_control/dataset_diff.py b/deeplake/core/version_control/dataset_diff.py\n--- a/deeplake/core/version_control/dataset_diff.py\n+++ b/deeplake/core/version_control/dataset_diff.py\n@@ -36,10 +36,13 @@\n                         [\n                             len(old_name).to_bytes(8, \"big\"),\n                             len(new_name).to_bytes(8, \"big\"),\n-                            (old_name + new_name).encode(\"utf-8\"),\n+                            (old_name + new_name),\n                         ]\n                     )\n-                    for old_name, new_name in self.renamed.items()\n+                    for old_name, new_name in map(\n+                        lambda n: (n[0].encode(\"utf-8\"), n[1].encode(\"utf-8\")),\n+                        self.renamed.items(),\n+                    )\n                 ),\n                 len(self.deleted).to_bytes(8, \"big\"),\n                 *(\n", "issue": "[BUG] Possibly unsafe conversion of DatasetDiff instance to bytes\n## \ud83d\udc1b\ud83d\udc1b Bug Report\r\n\r\n### \u2697\ufe0f Current Behavior\r\n\r\nThe code block\r\n\r\nhttps://github.com/activeloopai/deeplake/blob/c88925d8afa94841972fe4fd6f1ddeb1ede8dde0/deeplake/core/version_control/dataset_diff.py#L37-L39\r\n\r\nassumes `len(str.encode('utf-8')) == len(str)` which is not true in general.\r\n\r\n### \ud83e\uddf0 Possible Solution\r\n\r\nThe code block should read:\r\n```python\r\n                            len(old_name_encoded).to_bytes(8, \"big\"),\r\n                            len(new_name_encoded).to_bytes(8, \"big\"),\r\n                            old_name_encoded + new_name_encoded,\r\n```\r\nwhere\r\n```python\r\nold_name_encoded = old_name.encode(\"utf-8\")\r\nnew_name_encoded = new_name.encode(\"utf-8\")\r\n```\n", "before_files": [{"content": "from deeplake.core.storage.deeplake_memory_object import DeepLakeMemoryObject\nfrom deeplake.core.storage import LRUCache\nfrom deeplake.util.keys import get_dataset_diff_key\nimport typing\nfrom collections import OrderedDict\n\n\nclass DatasetDiff(DeepLakeMemoryObject):\n    def __init__(self) -> None:\n        self.is_dirty = False\n        self.info_updated = False\n        self.renamed: typing.OrderedDict = OrderedDict()\n        self.deleted: typing.List[str] = []\n\n    def tobytes(self) -> bytes:\n        \"\"\"Returns bytes representation of the dataset diff\n\n        The format stores the following information in order:\n        1. The first byte is a boolean value indicating whether the Dataset info was modified or not.\n        2. The next 8 bytes give the number of renamed tensors, let's call this m.\n        3. Next, there will be m blocks of bytes with the following format:\n            1. 8 + 8 bytes giving the length of old and new names, let's call them x and y.\n            2. x bytes of old name.\n            3. y bytes of new name.\n        4. The next 8 bytes give the number of deleted tensors, let's call this n.\n        5. Next, there will be n blocks of bytes with the following format:\n            1. 8 bytes giving the length of the name of the deleted tensor, let's call this z.\n            2. n bytes of name of the deleted tensor.\n        \"\"\"\n        return b\"\".join(\n            [\n                self.info_updated.to_bytes(1, \"big\"),\n                len(self.renamed).to_bytes(8, \"big\"),\n                *(\n                    b\"\".join(\n                        [\n                            len(old_name).to_bytes(8, \"big\"),\n                            len(new_name).to_bytes(8, \"big\"),\n                            (old_name + new_name).encode(\"utf-8\"),\n                        ]\n                    )\n                    for old_name, new_name in self.renamed.items()\n                ),\n                len(self.deleted).to_bytes(8, \"big\"),\n                *(\n                    b\"\".join([len(name).to_bytes(8, \"big\"), name.encode(\"utf-8\")])\n                    for name in self.deleted\n                ),\n            ]\n        )\n\n    @classmethod\n    def frombuffer(cls, data: bytes) -> \"DatasetDiff\":\n        \"\"\"Creates a DatasetDiff object from bytes\"\"\"\n        dataset_diff = cls()\n        dataset_diff.info_updated = bool(int.from_bytes(data[:1], \"big\"))\n        len_renamed = int.from_bytes(data[1:9], \"big\")\n        pos = 9\n        for _ in range(len_renamed):\n            len_old, len_new = (\n                int.from_bytes(data[pos : pos + 8], \"big\"),\n                int.from_bytes(data[pos + 8 : pos + 16], \"big\"),\n            )\n            pos += 16\n            old_name, new_name = (\n                data[pos : pos + len_old].decode(\"utf-8\"),\n                data[pos + len_old : pos + len_old + len_new].decode(\"utf-8\"),\n            )\n            pos += len_old + len_new\n            dataset_diff.renamed[old_name] = new_name\n        len_deleted = int.from_bytes(data[pos : pos + 8], \"big\")\n        pos += 8\n        for _ in range(len_deleted):\n            len_name = int.from_bytes(data[pos : pos + 8], \"big\")\n            pos += 8\n            name = data[pos : pos + len_name].decode(\"utf-8\")\n            pos += len_name\n            dataset_diff.deleted.append(name)\n        return dataset_diff\n\n    @property\n    def nbytes(self):\n        \"\"\"Returns number of bytes required to store the dataset diff\"\"\"\n        return 1\n\n    def modify_info(self) -> None:\n        \"\"\"Stores information that the info has changed\"\"\"\n        self.info_updated = True\n        self.is_dirty = True\n\n    def tensor_renamed(self, old_name, new_name):\n        \"\"\"Adds old and new name of a tensor that was renamed to renamed\"\"\"\n        for old, new in self.renamed.items():\n            if old_name == new:\n                if old == new_name:\n                    self.renamed.pop(old)\n                else:\n                    self.renamed[old] = new_name\n                break\n        else:\n            self.renamed[old_name] = new_name\n\n        self.is_dirty = True\n\n    def tensor_deleted(self, name):\n        \"\"\"Adds name of deleted tensor to deleted\"\"\"\n        if name not in self.deleted:\n            for old, new in self.renamed.items():\n                if name == new:\n                    self.renamed.pop(old)\n                    self.deleted.append(old)\n                    break\n            else:\n                self.deleted.append(name)\n            self.is_dirty = True\n\n\ndef load_dataset_diff(dataset):\n    storage: LRUCache = dataset.storage\n    path = get_dataset_diff_key(dataset.version_state[\"commit_id\"])\n    try:\n        diff = storage.get_deeplake_object(path, DatasetDiff)\n    except KeyError:\n        diff = DatasetDiff()\n    storage.register_deeplake_object(path, diff)\n    return diff\n", "path": "deeplake/core/version_control/dataset_diff.py"}], "after_files": [{"content": "from deeplake.core.storage.deeplake_memory_object import DeepLakeMemoryObject\nfrom deeplake.core.storage import LRUCache\nfrom deeplake.util.keys import get_dataset_diff_key\nimport typing\nfrom collections import OrderedDict\n\n\nclass DatasetDiff(DeepLakeMemoryObject):\n    def __init__(self) -> None:\n        self.is_dirty = False\n        self.info_updated = False\n        self.renamed: typing.OrderedDict = OrderedDict()\n        self.deleted: typing.List[str] = []\n\n    def tobytes(self) -> bytes:\n        \"\"\"Returns bytes representation of the dataset diff\n\n        The format stores the following information in order:\n        1. The first byte is a boolean value indicating whether the Dataset info was modified or not.\n        2. The next 8 bytes give the number of renamed tensors, let's call this m.\n        3. Next, there will be m blocks of bytes with the following format:\n            1. 8 + 8 bytes giving the length of old and new names, let's call them x and y.\n            2. x bytes of old name.\n            3. y bytes of new name.\n        4. The next 8 bytes give the number of deleted tensors, let's call this n.\n        5. Next, there will be n blocks of bytes with the following format:\n            1. 8 bytes giving the length of the name of the deleted tensor, let's call this z.\n            2. n bytes of name of the deleted tensor.\n        \"\"\"\n        return b\"\".join(\n            [\n                self.info_updated.to_bytes(1, \"big\"),\n                len(self.renamed).to_bytes(8, \"big\"),\n                *(\n                    b\"\".join(\n                        [\n                            len(old_name).to_bytes(8, \"big\"),\n                            len(new_name).to_bytes(8, \"big\"),\n                            (old_name + new_name),\n                        ]\n                    )\n                    for old_name, new_name in map(\n                        lambda n: (n[0].encode(\"utf-8\"), n[1].encode(\"utf-8\")),\n                        self.renamed.items(),\n                    )\n                ),\n                len(self.deleted).to_bytes(8, \"big\"),\n                *(\n                    b\"\".join([len(name).to_bytes(8, \"big\"), name.encode(\"utf-8\")])\n                    for name in self.deleted\n                ),\n            ]\n        )\n\n    @classmethod\n    def frombuffer(cls, data: bytes) -> \"DatasetDiff\":\n        \"\"\"Creates a DatasetDiff object from bytes\"\"\"\n        dataset_diff = cls()\n        dataset_diff.info_updated = bool(int.from_bytes(data[:1], \"big\"))\n        len_renamed = int.from_bytes(data[1:9], \"big\")\n        pos = 9\n        for _ in range(len_renamed):\n            len_old, len_new = (\n                int.from_bytes(data[pos : pos + 8], \"big\"),\n                int.from_bytes(data[pos + 8 : pos + 16], \"big\"),\n            )\n            pos += 16\n            old_name, new_name = (\n                data[pos : pos + len_old].decode(\"utf-8\"),\n                data[pos + len_old : pos + len_old + len_new].decode(\"utf-8\"),\n            )\n            pos += len_old + len_new\n            dataset_diff.renamed[old_name] = new_name\n        len_deleted = int.from_bytes(data[pos : pos + 8], \"big\")\n        pos += 8\n        for _ in range(len_deleted):\n            len_name = int.from_bytes(data[pos : pos + 8], \"big\")\n            pos += 8\n            name = data[pos : pos + len_name].decode(\"utf-8\")\n            pos += len_name\n            dataset_diff.deleted.append(name)\n        return dataset_diff\n\n    @property\n    def nbytes(self):\n        \"\"\"Returns number of bytes required to store the dataset diff\"\"\"\n        return 1\n\n    def modify_info(self) -> None:\n        \"\"\"Stores information that the info has changed\"\"\"\n        self.info_updated = True\n        self.is_dirty = True\n\n    def tensor_renamed(self, old_name, new_name):\n        \"\"\"Adds old and new name of a tensor that was renamed to renamed\"\"\"\n        for old, new in self.renamed.items():\n            if old_name == new:\n                if old == new_name:\n                    self.renamed.pop(old)\n                else:\n                    self.renamed[old] = new_name\n                break\n        else:\n            self.renamed[old_name] = new_name\n\n        self.is_dirty = True\n\n    def tensor_deleted(self, name):\n        \"\"\"Adds name of deleted tensor to deleted\"\"\"\n        if name not in self.deleted:\n            for old, new in self.renamed.items():\n                if name == new:\n                    self.renamed.pop(old)\n                    self.deleted.append(old)\n                    break\n            else:\n                self.deleted.append(name)\n            self.is_dirty = True\n\n\ndef load_dataset_diff(dataset):\n    storage: LRUCache = dataset.storage\n    path = get_dataset_diff_key(dataset.version_state[\"commit_id\"])\n    try:\n        diff = storage.get_deeplake_object(path, DatasetDiff)\n    except KeyError:\n        diff = DatasetDiff()\n    storage.register_deeplake_object(path, diff)\n    return diff\n", "path": "deeplake/core/version_control/dataset_diff.py"}]}