Skip to content

Filesystem corruption leads to crash in lfs_fs_size #306

@jimparis

Description

@jimparis

After a problem where my flash started returning all 0xff bytes, littlefs crashed in lfs_fs_size. This simulation reproduces the crash:

#include <stdio.h>
#include <string.h>
#include "lfs.h"

#define BLOCK_SIZE  4096
#define BLOCK_COUNT 64
uint8_t flash[BLOCK_SIZE * BLOCK_COUNT];

bool simulate_broken_flash = false;

int lfs_api_read(const struct lfs_config *c, lfs_block_t block,
                 lfs_off_t off, void *buffer, lfs_size_t size)
{
        if (simulate_broken_flash) {
                memset(buffer, 0xff, size);
                return 0;
        }

        memcpy(buffer, &flash[block * c->block_size + off], size);
        return 0;
}

int lfs_api_prog(const struct lfs_config *c, lfs_block_t block,
                 lfs_off_t off, const void *buffer, lfs_size_t size)
{
        memcpy(&flash[block * c->block_size + off], buffer, size);
        return 0;
}

int lfs_api_erase(const struct lfs_config *c, lfs_block_t block)
{
        memset(&flash[block * c->block_size], 0xff, c->block_size);
        return 0;
}

int lfs_api_sync(const struct lfs_config *c)
{
        return 0;
}

const struct lfs_config cfg = {
        // block device operations
        .read  = lfs_api_read,
        .prog  = lfs_api_prog,
        .erase = lfs_api_erase,
        .sync  = lfs_api_sync,

        // block device configuration
        .read_size = 1,
        .prog_size = 16,
        .block_size = BLOCK_SIZE,
        .block_count = BLOCK_COUNT,
        .cache_size = 2048,
        .lookahead_size = 128,
        .block_cycles = 1024,
};

int main(int argc, char **argv)
{
        lfs_t lfs;
        lfs_file_t file;

        memset(flash, 0xff, sizeof(flash));

        printf("format:\n");
        printf("ret=%d\n", lfs_format(&lfs, &cfg));

        printf("mount:\n");
        printf("ret=%d\n", lfs_mount(&lfs, &cfg));

        // simulate a problem (e.g. issue with SPI bus)
        simulate_broken_flash = true;

        printf("open:\n");
        printf("ret=%d\n", lfs_file_open(&lfs, &file, "test.txt", LFS_O_RDWR));

        printf("fs_size:\n");
        printf("ret=%d\n", lfs_fs_size(&lfs));

        return 0;
}

This patch avoids the crash:

diff --git a/lfs.c b/lfs.c
index e2ab1e572de4..3ad4538514ee 100644
--- a/lfs.c
+++ b/lfs.c
@@ -915,7 +915,7 @@ static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs,
             }
 
             // found a match for our fetcher?
-            if ((fmask & tag) == (fmask & ftag)) {
+            if ((fmask & tag) == (fmask & ftag) && cb) {
                 int res = cb(data, tag, &(struct lfs_diskoff){
                         dir->pair[0], off+sizeof(tag)});
                 if (res < 0) {

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs investigationno idea what is wrongneeds testall fixes need test coverage to prevent regression

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions