Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions TeXmacs/tests/tmu/201_71.tmu
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<TMU|<tuple|1.1.0|2026.1.2>>

<style|<tuple|generic|chinese|table-captions-above|number-europe|preview-ref>>

<\body>
<\hide-preamble>
<assign|theorem|<with|color|<hybrid|backcolor>|>>
</hide-preamble>

1111
</body>

<\initial>
<\collection>
<associate|page-medium|paper>
<associate|page-screen-margin|false>
</collection>
</initial>
9 changes: 9 additions & 0 deletions devel/201_71.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# [201_71] 修复导言区调用未定义的宏导致软件crash问题

## 如何测试
1. 打开 git/mogan/TeXmacs/tests/tmu/201_71.tmu 文件
2. `Ctrl+Shift+p`进入导言区
3. 鼠标光标移动到`backcolor`后回车应该不会导致软件闪退问题



11 changes: 8 additions & 3 deletions src/Typeset/Env/env_exec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ edit_env_rep::exec (tree t) {
return exec_frame_inverse (t);

default:
if (L (t) == UNINIT) return t;
if (L (t) < START_EXTENSIONS) {
int i, n= N (t);
// cout << "Executing " << t << "\n";
Expand Down Expand Up @@ -659,7 +660,7 @@ edit_env_rep::exec_with (tree t) {
write_update (vars[i], newv[i]);
tree r= exec (t[n - 1]);
for (i= k - 1; i >= 0; i--)
write_update (vars[i], oldv[i]);
if (L (oldv[i]) != UNINIT) write_update (vars[i], oldv[i]);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The fix prevents writing UNINIT values back, which avoids crashes but changes the semantics of the WITH construct. Variables that didn't exist before a WITH block will now persist after the block exits, instead of returning to their undefined state. Consider using env->reset(vars[i]) instead of skipping the write_update when oldv[i] is UNINIT, to properly restore the undefined state.

Copilot uses AI. Check for mistakes.

tree u (WITH, n);
for (i= 0; i < k; i++) {
Expand Down Expand Up @@ -852,7 +853,11 @@ edit_env_rep::exec_value (tree t) {
if (N (t) < 1) return tree (ERROR, "bad value");
tree r= exec (t[0]);
if (is_compound (r)) return tree (ERROR, "bad value");
return exec (read (r->label));
string name= r->label;
if (!provides (name)) return "";
tree value= read (name);
if (L (value) == UNINIT) return "";
return exec (value);
}

tree
Expand Down Expand Up @@ -2667,7 +2672,7 @@ edit_env_rep::exec_until_with (tree t, path p, string var, int level) {
return true;
}
for (i= k - 1; i >= 0; i--)
write_update (vars[i], oldv[i]);
if (L (oldv[i]) != UNINIT) write_update (vars[i], oldv[i]);
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The fix prevents writing UNINIT values back, which avoids crashes but changes the semantics of the WITH construct. Variables that didn't exist before a WITH block will now persist after the block exits, instead of returning to their undefined state. Consider using env->reset(vars[i]) to properly restore the undefined state, similar to line 663 in exec_with.

Suggested change
if (L (oldv[i]) != UNINIT) write_update (vars[i], oldv[i]);
if (L (oldv[i]) != UNINIT)
write_update (vars[i], oldv[i]);
else
reset (vars[i]);

Copilot uses AI. Check for mistakes.
STACK_DELETE_ARRAY (vars);
STACK_DELETE_ARRAY (oldv);
STACK_DELETE_ARRAY (newv);
Expand Down