回答編集履歴

3

タイムトラベル

2021/03/24 17:26

投稿

yumetodo
yumetodo

スコア5850

test CHANGED
@@ -116,7 +116,7 @@
116
116
 
117
117
 
118
118
 
119
- 処理系によっては未定義動作を積極的に活用して最適化に利用したり、あるいは範囲外アクセスを検出するために確保したメモリー領域間になにか特殊な詰め物をして上書きを検出しようとするかもしれません。
119
+ 処理系によっては未定義動作を積極的に活用して最適化に利用したり、[タイムトラベルしたり](https://cpplover.blogspot.com/2014/06/old-new-thing.html)、あるいは範囲外アクセスを検出するために確保したメモリー領域間になにか特殊な詰め物をして上書きを検出しようとするかもしれません。
120
120
 
121
121
 
122
122
 

2

2021/03/24 17:26

投稿

yumetodo
yumetodo

スコア5850

test CHANGED
@@ -46,7 +46,7 @@
46
46
 
47
47
  ```
48
48
 
49
- <--4byte->
49
+ <--1byte->
50
50
 
51
51
  | s[0] |
52
52
 
@@ -77,6 +77,10 @@
77
77
  |ret addr|
78
78
 
79
79
  ```
80
+
81
+
82
+
83
+ (上に行くほどメモリー上の番地が若い、スタックの上の方というイメージで、もちろんそんな概念C/C++にはない)
80
84
 
81
85
 
82
86
 

1

UB

2021/03/24 17:25

投稿

yumetodo
yumetodo

スコア5850

test CHANGED
@@ -34,26 +34,90 @@
34
34
 
35
35
 
36
36
 
37
- 1. 関数を呼び出すとき、その関数を呼び出し終えたあとに実行するべき命令が置かれたメモリー領域へのポインタをスタックにつむ。
37
+ 1. 関数を呼び出すとき、その関数を呼び出し終えたあとに実行するべき命令が置かれたメモリー領域へのポインタをスタックにつむ。(以下return address=ret addr, 仮に4byte)
38
38
 
39
39
  2. その後で関数内での自動変数の領域をスタックに積む
40
40
 
41
41
 
42
42
 
43
- するとこういうメモリー配置になる可能性が考えられます。
43
+ すると先の例で関数fが呼び出された直後、こういうメモリー配置になる可能性が考えられます。
44
44
 
45
45
 
46
46
 
47
47
  ```
48
48
 
49
- <--8bit-->
49
+ <--4byte->
50
50
 
51
51
  | s[0] |
52
52
 
53
- | s[0] |
53
+ | s[1] |
54
54
 
55
- | s[0] |
55
+ | s[2] |
56
56
 
57
- | s[0] |
57
+ | s[3] |
58
58
 
59
- | s[0] |v
59
+ | s[4] |
60
+
61
+ | s[5] |
62
+
63
+ | s[6] |
64
+
65
+ | s[7] |
66
+
67
+ | s[8] |
68
+
69
+ | s[9] |
70
+
71
+ |ret addr|
72
+
73
+ |ret addr|
74
+
75
+ |ret addr|
76
+
77
+ |ret addr|
78
+
79
+ ```
80
+
81
+
82
+
83
+ このとき先の例のfor文で範囲外アクセスが行われた場合、`s[9]`を超えて`ret addr`の一部分にまで書き換えが及びそうです。
84
+
85
+
86
+
87
+ すると関数の呼び出し元に戻ることすらできなくなるという可能性が考えられます。
88
+
89
+
90
+
91
+ ---
92
+
93
+
94
+
95
+ さてここまでの話を踏まえ次を考えます。
96
+
97
+
98
+
99
+ > その考察から、質問内容であるscanfで定義された文字数以上の文字を入力すると後ろの領域、つまり1つ前に定義した変数に代入されるのではないかという予想をしています。
100
+
101
+
102
+
103
+ 大事なことなので3度めですが言及すると**考察が無意味**です。しかし今回の処理系はたまたまそういう振る舞いをしていると観測することができました、ということはできます。
104
+
105
+
106
+
107
+ 例えば今回の質問者さんの例で`scanf`に`malloc`した領域を渡したらどうなるのかなど観測してみるのも面白いかもしれません。
108
+
109
+
110
+
111
+ ---
112
+
113
+
114
+
115
+ 処理系によっては未定義動作を積極的に活用して最適化に利用したり、あるいは範囲外アクセスを検出するために確保したメモリー領域間になにか特殊な詰め物をして上書きを検出しようとするかもしれません。
116
+
117
+
118
+
119
+ ---
120
+
121
+
122
+
123
+ しかし確実に言えるのはそもそも未定義動作を踏むな、踏んだ状態についてなんらかの考察をするなということです。