diff --git a/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp b/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp index 21e64bd458..4082367928 100644 --- a/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp +++ b/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp @@ -108,8 +108,8 @@ DirectoryIterator::Get(char* name, size_t* _nameLength, ino_t* _id) entry->InodeID(), entry->Length(), length, entry->FileType()); if (*_nameLength > 0) { - if (*_nameLength < length) - length = *_nameLength - 1; + if (length + 1 > *_nameLength) + return B_BUFFER_OVERFLOW; memcpy(name, entry->name, length); name[length] = '\0'; diff --git a/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp b/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp index 9842fd23cb..b5fcdfce23 100644 --- a/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp +++ b/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp @@ -1414,27 +1414,44 @@ ext2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie, struct dirent *dirent, size_t bufferSize, uint32 *_num) { DirectoryIterator *iterator = (DirectoryIterator *)_cookie; - - size_t length = bufferSize; - ino_t id; - status_t status = iterator->GetNext(dirent->d_name, &length, &id); - if (status == B_ENTRY_NOT_FOUND) { - *_num = 0; - return B_OK; - } else if (status != B_OK) - return status; - - status = iterator->Next(); - if (status != B_OK && status != B_ENTRY_NOT_FOUND) - return status; - Volume* volume = (Volume*)_volume->private_volume; - dirent->d_dev = volume->ID(); - dirent->d_ino = id; - dirent->d_reclen = sizeof(struct dirent) + length; + uint32 maxCount = *_num; + uint32 count = 0; - *_num = 1; + while (count < maxCount && bufferSize > sizeof(struct dirent)) { + + size_t length = bufferSize - sizeof(struct dirent) + 1; + ino_t id; + + status_t status = iterator->GetNext(dirent->d_name, &length, &id); + if (status == B_ENTRY_NOT_FOUND) + break; + + if (status == B_BUFFER_OVERFLOW) { + // the remaining name buffer length was too small + if (count == 0) + return B_BUFFER_OVERFLOW; + break; + } + + if (status != B_OK) + return status; + + status = iterator->Next(); + if (status != B_OK && status != B_ENTRY_NOT_FOUND) + return status; + + dirent->d_dev = volume->ID(); + dirent->d_ino = id; + dirent->d_reclen = sizeof(struct dirent) + length; + + bufferSize -= dirent->d_reclen; + dirent = (struct dirent*)((uint8*)dirent + dirent->d_reclen); + count++; + } + + *_num = count; return B_OK; }