Skip to content

Add C-language port of the MassData API with a Visual Studio 2026 test project#40

Merged
nevstop merged 5 commits into
mainfrom
copilot/add-c-support-for-massdata
Apr 25, 2026
Merged

Add C-language port of the MassData API with a Visual Studio 2026 test project#40
nevstop merged 5 commits into
mainfrom
copilot/add-c-support-for-massdata

Conversation

Copilot AI commented Apr 24, 2026

Copy link
Copy Markdown
Contributor
  • Implement C-language port of the MassData API
  • Translate all comments to Chinese, upgrade to VS2026, move tests to c/_test/vs/
  • Add c/** to paths-ignore in both LabVIEW workflows so changes under c/ no longer trigger them

Copilot AI changed the title [WIP] Add C support for massdata with API consistency Add C-language port of the MassData API with a Visual Studio test project Apr 24, 2026
Copilot AI requested a review from nevstop April 24, 2026 15:35

@nevstop nevstop left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 所有的注释改为中文注释
  2. 工程修改为 vs2026
  3. 测试放到 c/_test/vs/.. 目录下

Comment thread README(zh-cn).md
Comment thread README.md
@nevstop

nevstop commented Apr 25, 2026

Copy link
Copy Markdown
Contributor

@copilot 根据之前上的comments修改

Copilot AI commented Apr 25, 2026

Copy link
Copy Markdown
Contributor Author
  1. 所有的注释改为中文注释
  2. 工程修改为 vs2026
  3. 测试放到 c/_test/vs/.. 目录下

已在 5eb1974 中处理:1) 头文件、实现与测试程序中的所有注释(含 Doxygen)改为中文;2) VS 工程升级到 VS2026(PlatformToolset=v145VCProjectVersion=18.0# Visual Studio Version 18);3) 测试整体迁移到 c/_test/vs/,并相应更新工程内的相对路径。

Copilot AI changed the title Add C-language port of the MassData API with a Visual Studio test project Add C-language port of the MassData API with a Visual Studio 2026 test project Apr 25, 2026
Copilot AI requested a review from nevstop April 25, 2026 03:08
@nevstop nevstop marked this pull request as ready for review April 25, 2026 03:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a C-language implementation of the MassData Parameter Support API (matching the LabVIEW VI surface), plus a standalone Visual Studio test project and repo hygiene updates so C-only changes don’t trigger the LabVIEW CI workflows.

Changes:

  • Added csm_massdata C API implementation + public header with Doxygen docs (Chinese).
  • Added a Visual Studio solution/project with a console-based test runner covering the exported API.
  • Updated .gitignore and adjusted LabVIEW GitHub Actions workflows to ignore changes under c/**.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
c/src/csm_massdata.c Implements the global ring-buffer, encoder/decoder, datatype parsing, and status API.
c/include/csm_massdata.h Public C API + documentation mirroring LabVIEW VI naming/semantics.
c/_test/vs/test_main.c Console test suite validating correct behavior and major error cases.
c/_test/vs/csm_massdata_test.vcxproj VS project configuration to build the C implementation and tests.
c/_test/vs/csm_massdata_test.vcxproj.filters VS filters for source/header organization.
c/_test/vs/csm_massdata_test.sln VS solution wrapper for the test project.
c/README.md C port overview + build/test instructions.
.gitignore Ignores Visual Studio build artifacts under c/.
.github/workflows/Check_Broken_VIs.yml Adds c/** to paths-ignore so C-only changes don’t trigger.
.github/workflows/Build_VIPM_Library.yml Adds c/** to paths-ignore so C-only changes don’t trigger.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread c/src/csm_massdata.c
Comment on lines +112 to +132
if (strncmp(p, "Start:", 6) != 0) {
return CSM_MASSDATA_ERR_PARSE;
}
p += 6;
tmp = strtoull(p, &end, 10);
if (end == p || *end != ';') {
return CSM_MASSDATA_ERR_PARSE;
}
*start_out = (uint64_t)tmp;
p = end + 1;

if (strncmp(p, "Size:", 5) != 0) {
return CSM_MASSDATA_ERR_PARSE;
}
p += 5;
tmp = strtoull(p, &end, 10);
if (end == p) {
return CSM_MASSDATA_ERR_PARSE;
}
*size_out = (uint64_t)tmp;
p = end;

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

csm_massdata_parse() uses strtoull without checking errno/ULLONG_MAX overflow, so extremely large Start/Size values can be accepted and then cast into uint64_t silently. Add errno checking (and optionally an explicit upper bound check) to reject out-of-range values with CSM_MASSDATA_ERR_PARSE.

Copilot uses AI. Check for mistakes.
Comment thread c/src/csm_massdata.c
Comment on lines +134 to +156
/* 可选的 ;DataType:<T> 后缀。 */
if (data_type != NULL && data_type_cap > 0u) {
data_type[0] = '\0';
}
if (*p == '\0') {
return CSM_MASSDATA_OK;
}
if (*p != ';') {
return CSM_MASSDATA_ERR_PARSE;
}
p++;
if (strncmp(p, "DataType:", 9) != 0) {
return CSM_MASSDATA_ERR_PARSE;
}
p += 9;
if (data_type != NULL && data_type_cap > 0u) {
size_t len = strlen(p);
if (len + 1u > data_type_cap) {
return CSM_MASSDATA_ERR_BUFFER_TOO_SMALL;
}
memcpy(data_type, p, len + 1u);
}
return CSM_MASSDATA_OK;

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

csm_massdata_parse() accepts any trailing characters after DataType: (and when data_type == NULL, it also accepts trailing characters without validating termination). Given the documented format <MassData>Start:<N>;Size:<N>[;DataType:<T>], the parser should ensure the string ends after the optional DataType value (and ideally reject DataType values containing ;, <, > to match the encoder’s constraints).

Copilot uses AI. Check for mistakes.
Comment thread c/src/csm_massdata.c
Comment on lines +52 to +68
static void csm_massdata_lazy_init(void)
{
if (g_state.initialized) {
return;
}
/* 第一次调用本模块的 API 时负责分配默认缓冲区。
* 一旦初始化完成,该标志将由互斥量保护;但首次分配本身
* 在多线程程序中存在竞态,因此关心线程安全的调用方应当
* 在程序启动时主动调用 CSM_ConfigMassDataParameterCacheSize()。 */
g_state.buffer = (uint8_t *)malloc(CSM_MASSDATA_DEFAULT_CACHE_SIZE);
g_state.capacity = (g_state.buffer != NULL) ? CSM_MASSDATA_DEFAULT_CACHE_SIZE : 0u;
g_state.write_total = 0u;
memset(&g_state.last_read, 0, sizeof(g_state.last_read));
memset(&g_state.last_write, 0, sizeof(g_state.last_write));
CSM_MUTEX_INIT(&g_state.mutex);
g_state.initialized = 1;
}

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

csm_massdata_lazy_init() is not thread-safe: multiple threads can concurrently allocate g_state.buffer and initialize g_state.mutex, leading to leaks and undefined behavior (double init of mutex / data race on initialized). Since public APIs call this without external synchronization, initialization should be made thread-safe (e.g., pthread_once / InitOnceExecuteOnce / a separate static init lock) rather than relying on the caller to serialize startup.

Copilot uses AI. Check for mistakes.
Comment thread c/include/csm_massdata.h Outdated
Comment on lines +30 to +31
* 本头文件中所有公开函数均为线程安全。多个线程的并发调用
* 会通过内部互斥量串行化执行。

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The header states all public functions are thread-safe, but the implementation’s lazy initialization has a documented race on first use. Either make initialization thread-safe or adjust the API docs to reflect that callers must initialize/configure early to avoid concurrent first-call races.

Suggested change
* 本头文件中所有公开函数均为线程安全多个线程的并发调用
* 会通过内部互斥量串行化执行
* 在内部状态完成初始化后公开函数的并发调用会通过内部互斥量
* 串行化执行首次使用可能触发延迟初始化为避免首次调用时的
* 并发竞争调用方应在进入多线程阶段前于单线程上下文中先完成
* 一次初始化/配置调用再让多个线程并发访问本 API

Copilot uses AI. Check for mistakes.
Comment thread c/src/csm_massdata.c Outdated
Comment on lines +351 to +358
uint64_t end = start + size;
uint64_t oldest = (g_state.write_total > (uint64_t)g_state.capacity)
? g_state.write_total - (uint64_t)g_state.capacity
: 0u;
if (start < oldest || end > g_state.write_total) {
CSM_MUTEX_UNLOCK(&g_state.mutex);
return CSM_MASSDATA_ERR_OVERWRITTEN;
}

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end = start + size can overflow uint64_t, which can incorrectly pass the residency check and return unrelated bytes instead of CSM_MASSDATA_ERR_OVERWRITTEN for crafted arguments (e.g., Start near UINT64_MAX). Add an overflow check before the addition (e.g., if (size > 0 && start > UINT64_MAX - size) ...) and validate start <= write_total and end <= write_total using non-overflowing comparisons.

Suggested change
uint64_t end = start + size;
uint64_t oldest = (g_state.write_total > (uint64_t)g_state.capacity)
? g_state.write_total - (uint64_t)g_state.capacity
: 0u;
if (start < oldest || end > g_state.write_total) {
CSM_MUTEX_UNLOCK(&g_state.mutex);
return CSM_MASSDATA_ERR_OVERWRITTEN;
}
uint64_t oldest = (g_state.write_total > (uint64_t)g_state.capacity)
? g_state.write_total - (uint64_t)g_state.capacity
: 0u;
uint64_t end;
if (size > 0u && start > UINT64_MAX - size) {
CSM_MUTEX_UNLOCK(&g_state.mutex);
return CSM_MASSDATA_ERR_OVERWRITTEN;
}
if (start < oldest || start > g_state.write_total) {
CSM_MUTEX_UNLOCK(&g_state.mutex);
return CSM_MASSDATA_ERR_OVERWRITTEN;
}
end = start + size;
if (end > g_state.write_total) {
CSM_MUTEX_UNLOCK(&g_state.mutex);
return CSM_MASSDATA_ERR_OVERWRITTEN;
}

Copilot uses AI. Check for mistakes.
Comment thread c/src/csm_massdata.c
Comment on lines +327 to +336
csm_massdata_lazy_init();

*data_size_out = (size_t)size;

if (size > 0u && data == NULL) {
return CSM_MASSDATA_ERR_INVALID_ARG;
}
if (size > (uint64_t)data_cap) {
return CSM_MASSDATA_ERR_BUFFER_TOO_SMALL;
}

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*data_size_out = (size_t)size; is assigned before range validation and can truncate on 32-bit platforms (or when size > SIZE_MAX), potentially returning a misleading required size even when the function returns an error. Consider validating size <= SIZE_MAX first and only then populating data_size_out (or define how values larger than size_t are reported).

Copilot uses AI. Check for mistakes.
@nevstop

nevstop commented Apr 25, 2026

Copy link
Copy Markdown
Contributor

@copilot apply changes based on the comments in this thread

Copilot AI commented Apr 25, 2026

Copy link
Copy Markdown
Contributor Author

@copilot apply changes based on the comments in this thread

已在 cd7227c 中完成所有六处修复:

  1. strtoull overflow — 每次调用前 errno = 0,调用后检测 errno != 0(即 ERANGE)。
  2. DataType: 后缀尾部验证 — 解析出值后扫描确认字符合法(无 ;/</>)且字符串以 \0 结尾;data_type == NULL 时同样验证。
  3. 线程安全延迟初始化 — POSIX 使用 pthread_once,Windows 使用 InitOnceExecuteOnce,替代原有带竞态的 initialized 标志检查。
  4. 头文件线程安全文档 — 更新 @par 线程安全 段落,说明平台原语及建议提前调用 CSM_ConfigMassDataParameterCacheSize()
  5. *data_size_out 赋值顺序 — 先做 SIZE_MAX 检查和 data == NULL 检查,再赋值,并对 >SIZE_MAXsize 返回 ERR_PARSE
  6. start + size 溢出 — 加法前检查 start > UINT64_MAX - size,并将 startend 的边界校验拆开,使用不溢出的比较式。

@nevstop nevstop merged commit e4e01aa into main Apr 25, 2026
@nevstop nevstop deleted the copilot/add-c-support-for-massdata branch April 25, 2026 11:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

massdata 的第三方语言支持: C

3 participants