Skip to content

[Code scan] Harden LAMMPS DPLR and spin option argument parsing #5645

Description

@njzjz

Found during a Codex global scan of deepmodeling/deepmd-kit at commit 73de44b1f94471b2e3bdb6b11f57b34d7bc791bb.

Problem

Several LAMMPS option parsers read arguments after a keyword without first checking that enough arguments remain.

Evidence:

  • In FixDPLR, the model option checks iarg + 1 > narg, but then reads arg[iarg + 1]; when the keyword is the final token, the check passes and the code reads past the argv array:
    if (string(arg[iarg]) == string("model")) {
    if (iarg + 1 > narg) {
    error->all(FLERR, "Illegal fix adapt command");
    }
    model = string(arg[iarg + 1]);
    iarg += 2;
  • The efield option needs three following values, but checks iarg + 3 > narg before reading through arg[iarg + 3]:
    } else if (string(arg[iarg]) == string("efield")) {
    if (iarg + 3 > narg) {
    error->all(FLERR,
    "Illegal fix adapt command, efield should be provided 3 "
    "float numbers");
    }
    if (utils::strmatch(arg[iarg + 1], "^v_")) {
    xstr = utils::strdup(arg[iarg + 1] + 2);
    } else {
    efield[0] = qe2f * utils::numeric(FLERR, arg[iarg + 1], false, lmp);
    xstyle = CONSTANT;
    }
    if (utils::strmatch(arg[iarg + 2], "^v_")) {
    ystr = utils::strdup(arg[iarg + 2] + 2);
    } else {
    efield[1] = qe2f * utils::numeric(FLERR, arg[iarg + 2], false, lmp);
    ystyle = CONSTANT;
    }
    if (utils::strmatch(arg[iarg + 3], "^v_")) {
    zstr = utils::strdup(arg[iarg + 3] + 2);
    } else {
    efield[2] = qe2f * utils::numeric(FLERR, arg[iarg + 3], false, lmp);
    zstyle = CONSTANT;
    }
    iarg += 4;
  • pair_style deepmd reads arg[iarg + 1] for relative and relative_v without any bounds/key check:
    } else if (string(arg[iarg]) == string("relative")) {
    out_rel = 1;
    eps = atof(arg[iarg + 1]) / ener_unit_cvt_factor;
    iarg += 2;
    } else if (string(arg[iarg]) == string("relative_v")) {
    out_rel_v = 1;
    eps_v = atof(arg[iarg + 1]) / ener_unit_cvt_factor;
    iarg += 2;
  • pair_style deepmd also reads virtual_len and spin_norm values in loops without checking that numb_types_spin values remain:
    } else if (string(arg[iarg]) == string("virtual_len")) {
    virtual_len.resize(numb_types_spin);
    for (int ii = 0; ii < numb_types_spin; ++ii) {
    virtual_len[ii] = atof(arg[iarg + ii + 1]);
    }
    iarg += numb_types_spin + 1;
    } else if (string(arg[iarg]) == string("spin_norm")) {
    spin_norm.resize(numb_types_spin);
    for (int ii = 0; ii < numb_types_spin; ++ii) {
    spin_norm[ii] = atof(arg[iarg + ii + 1]);
    }
    iarg += numb_types_spin + 1;
  • pair_style deepspin has the same unchecked relative/relative_v and spin-option reads:
    } else if (string(arg[iarg]) == string("relative")) {
    out_rel = 1;
    eps = atof(arg[iarg + 1]) / ener_unit_cvt_factor;
    iarg += 2;
    } else if (string(arg[iarg]) == string("relative_v")) {
    out_rel_v = 1;
    eps_v = atof(arg[iarg + 1]) / ener_unit_cvt_factor;
    iarg += 2;
    } else if (string(arg[iarg]) == string("virtual_len")) {
    virtual_len.resize(numb_types_spin);
    for (int ii = 0; ii < numb_types_spin; ++ii) {
    virtual_len[ii] = atof(arg[iarg + ii + 1]);
    }
    iarg += numb_types_spin + 1;
    } else if (string(arg[iarg]) == string("spin_norm")) {
    spin_norm.resize(numb_types_spin);
    for (int ii = 0; ii < numb_types_spin; ++ii) {
    spin_norm[ii] = atof(arg[iarg + ii + 1]);
    }
    iarg += numb_types_spin + 1;

Impact

Malformed LAMMPS input such as a trailing relative, relative_v, virtual_len, spin_norm, model, or incomplete efield option can read beyond the arg array and crash instead of producing a normal LAMMPS input error.

Suggested Fix

Use >= narg style bounds checks before every argument read and reject another keyword where a numeric value is required. Replace the type_associate parity assert with a runtime error->all() as part of the same parser hardening. Add parser tests for truncated options.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    In Progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions