Skip to content

Commit 1c500cb

Browse files
committed
VM: Stack safety
1 parent e6aa754 commit 1c500cb

2 files changed

Lines changed: 43 additions & 19 deletions

File tree

include/openminecraft/vm/pixeltower/om_pixeltower_interpreter.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ class OMInterpreter
3333
util::OMResult<std::any, err::OMValidationError> execute(std::shared_ptr<OMClass> clazz, std::string method,
3434
std::string sig);
3535
util::OMResult<std::any, err::OMValidationError> executeDynamic(std::string clazz, std::string method,
36-
std::string sig);
36+
std::string sig,
37+
std::shared_ptr<OMFrameMetadata> frame);
3738
util::OMResult<std::any, err::OMValidationError> execute(std::shared_ptr<OMClass> clazz,
3839
std::shared_ptr<OMMethodInfo> mi);
3940

@@ -65,7 +66,7 @@ class OMInterpreter
6566
util::OMResult<std::any, err::OMValidationError> checkType(std::shared_ptr<OMFrameMetadata> frame, std::any data,
6667
std::string desc);
6768
std::string fetchName(OMArrayType type);
68-
void writeStackTop(void *target, std::string desc);
69+
void writeStackTop(void *target, std::string desc, std::shared_ptr<OMFrameMetadata> frame);
6970
std::string fetchCurrentPosition(std::shared_ptr<OMFrameMetadata> frame);
7071
util::OMResult<std::any, err::OMValidationError> popFrame(std::shared_ptr<OMFrameMetadata> frame);
7172

src/vm/pixeltower/om_pixeltower_interpreter.cpp

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@ extern std::string ARRAY_TYPE;
3232
namespace openminecraft::vm::pixeltower::runtime
3333
{
3434
#define STACK_ACCESS stack[std::this_thread::get_id()]
35+
#define SAFE_STACK_POP \
36+
if (STACK_ACCESS.empty()) \
37+
{ \
38+
throw err::OMValidationError{err::Instructions, "Why the stack is empty?!", fetchCurrentPosition(frame)}; \
39+
} \
40+
STACK_ACCESS.pop();
41+
#define STACK_CHECK \
42+
if (STACK_ACCESS.empty()) \
43+
{ \
44+
throw err::OMValidationError{err::Instructions, "Why the stack is empty?!", fetchCurrentPosition(frame)}; \
45+
}
46+
3547
OMInterpreter::OMInterpreter(OMPixelTower &tower) : tower(tower), logger("pixeltower/OMInterpreter", this)
3648
{
3749
}
@@ -56,7 +68,8 @@ OMResult<std::any, err::OMValidationError> OMInterpreter::execute(std::shared_pt
5668
{err::ClassLoader, "method not found", fmt::format("{}.{}{}", clazz->name, method, sig)});
5769
}
5870
OMResult<std::any, err::OMValidationError> OMInterpreter::executeDynamic(std::string clazz, std::string method,
59-
std::string sig)
71+
std::string sig,
72+
std::shared_ptr<OMFrameMetadata> frame)
6073
{
6174
std::stack<std::any> tempst;
6275
int temp = 0;
@@ -70,8 +83,9 @@ OMResult<std::any, err::OMValidationError> OMInterpreter::executeDynamic(std::st
7083

7184
for (int i = 0; i < result.unwrap().first.size(); i++)
7285
{
86+
STACK_CHECK;
7387
tempst.push(STACK_ACCESS.top());
74-
STACK_ACCESS.pop();
88+
SAFE_STACK_POP;
7589
}
7690

7791
if (std::type_index(STACK_ACCESS.top().type()) == std::type_index(typeid(void *)))
@@ -130,6 +144,7 @@ OMResult<std::any, err::OMValidationError> OMInterpreter::execute(std::shared_pt
130144

131145
for (int argid = args - 1; argid >= 0; argid--)
132146
{
147+
STACK_CHECK;
133148
frame->local[argid] = STACK_ACCESS.top();
134149
auto target = checkType(frame, STACK_ACCESS.top(), types[argid]);
135150
switch (target.type)
@@ -141,7 +156,7 @@ OMResult<std::any, err::OMValidationError> OMInterpreter::execute(std::shared_pt
141156
logger.debug(target.unwrap_err().what());
142157
}
143158
}
144-
STACK_ACCESS.pop();
159+
SAFE_STACK_POP;
145160
}
146161
}
147162

@@ -516,30 +531,33 @@ std::string OMInterpreter::fetchName(OMArrayType type)
516531
}
517532
}
518533
// TODO: other types
519-
void OMInterpreter::writeStackTop(void *target, std::string desc)
534+
void OMInterpreter::writeStackTop(void *target, std::string desc, std::shared_ptr<OMFrameMetadata> frame)
520535
{
536+
STACK_CHECK;
521537
auto it = std::type_index(STACK_ACCESS.top().type());
522538

523539
if (it == std::type_index(typeid(int)))
524540
{
525541
*((int *)target) = std::any_cast<int>(STACK_ACCESS.top());
526542
}
527543

528-
STACK_ACCESS.pop();
544+
SAFE_STACK_POP;
529545
}
530546
std::string OMInterpreter::fetchCurrentPosition(std::shared_ptr<OMFrameMetadata> frame)
531547
{
532548
return fmt::format("{}.{}{} + {}", frame->clazz->name, frame->method->name, frame->method->desc, frame->offset);
533549
}
534550
util::OMResult<std::any, err::OMValidationError> OMInterpreter::operand_ireturn(std::shared_ptr<OMFrameMetadata> frame)
535551
{
552+
STACK_CHECK;
536553
auto ret = STACK_ACCESS.top();
537554
auto l = popFrame(frame);
538555
STACK_ACCESS.push(ret);
539556
return l;
540557
}
541558
OMResult<std::any, err::OMValidationError> OMInterpreter::operand_putfield(std::shared_ptr<OMFrameMetadata> frame)
542559
{
560+
STACK_CHECK;
543561
auto mrIdx = binary::be16ToNative(*(uint16_t *)(frame->codePointer + frame->offset + 1));
544562
auto temp1 = frame->clazz->mapping->at(mrIdx)->to<OMClassConstantFieldRef>();
545563
auto temp2 = frame->clazz->mapping->at(temp1->classIndex)->to<OMClassConstantClass>();
@@ -557,9 +575,9 @@ OMResult<std::any, err::OMValidationError> OMInterpreter::operand_putfield(std::
557575

558576
frame->offset += 3;
559577
auto value = STACK_ACCESS.top();
560-
STACK_ACCESS.pop();
578+
SAFE_STACK_POP;
561579
auto item = STACK_ACCESS.top();
562-
STACK_ACCESS.pop();
580+
SAFE_STACK_POP;
563581
STACK_ACCESS.push(value);
564582
if (std::type_index(item.type()) != std::type_index(typeid(void *)))
565583
{
@@ -570,7 +588,7 @@ OMResult<std::any, err::OMValidationError> OMInterpreter::operand_putfield(std::
570588
{
571589
if (fi->name == name && (fi->accessFlag & JVM_Acc_Static) == 0)
572590
{
573-
writeStackTop(OBJECT_ACCESS(std::any_cast<void *>(item), fi->offset), fi->desc);
591+
writeStackTop(OBJECT_ACCESS(std::any_cast<void *>(item), fi->offset), fi->desc, frame);
574592
return OMResult<std::any, err::OMValidationError>::ok(nullptr);
575593
}
576594
}
@@ -601,7 +619,7 @@ OMResult<std::any, err::OMValidationError> OMInterpreter::operand_putstatic(std:
601619
{
602620
if (fi->name == name && (fi->accessFlag & JVM_Acc_Static))
603621
{
604-
writeStackTop(OBJECT_ACCESS(res.unwrap()->staticFieldBlock, fi->offset), fi->desc);
622+
writeStackTop(OBJECT_ACCESS(res.unwrap()->staticFieldBlock, fi->offset), fi->desc, frame);
605623
return OMResult<std::any, err::OMValidationError>::ok(nullptr);
606624
}
607625
}
@@ -612,8 +630,9 @@ OMResult<std::any, err::OMValidationError> OMInterpreter::operand_putstatic(std:
612630
}
613631
void OMInterpreter::operand_istore_n(std::shared_ptr<OMFrameMetadata> frame)
614632
{
633+
STACK_CHECK;
615634
auto item = STACK_ACCESS.top();
616-
STACK_ACCESS.pop();
635+
SAFE_STACK_POP;
617636
frame->local[frame->codePointer[frame->offset] - op_istore_n(0)] = item;
618637
frame->offset++;
619638
}
@@ -629,7 +648,7 @@ OMResult<std::any, err::OMValidationError> OMInterpreter::operand_invokeinterfac
629648
auto name = frame->clazz->mapping->at(temp3->nameIndex)->to<OMClassConstantUtf8>()->data;
630649
auto desc = frame->clazz->mapping->at(temp3->descIndex)->to<OMClassConstantUtf8>()->data;
631650

632-
auto r = executeDynamic(cls, name, desc);
651+
auto r = executeDynamic(cls, name, desc, frame);
633652
if (r.type == util::Err)
634653
{
635654
return OMResult<std::any, err::OMValidationError>::err(r.unwrap_err());
@@ -641,8 +660,9 @@ OMResult<std::any, err::OMValidationError> OMInterpreter::operand_invokeinterfac
641660
}
642661
void OMInterpreter::operand_astore_n(std::shared_ptr<OMFrameMetadata> frame)
643662
{
663+
STACK_CHECK;
644664
auto item = STACK_ACCESS.top();
645-
STACK_ACCESS.pop();
665+
SAFE_STACK_POP;
646666
frame->local[frame->codePointer[frame->offset] - op_astore_n(0)] = item;
647667
frame->offset++;
648668
}
@@ -669,10 +689,11 @@ void OMInterpreter::operand_dconst_n(std::shared_ptr<OMFrameMetadata> frame)
669689
util::OMResult<std::any, err::OMValidationError> OMInterpreter::operand_if_acmpne(
670690
std::shared_ptr<OMFrameMetadata> frame)
671691
{
692+
STACK_CHECK;
672693
auto a1 = STACK_ACCESS.top();
673-
STACK_ACCESS.pop();
694+
SAFE_STACK_POP;
674695
auto a2 = STACK_ACCESS.top();
675-
STACK_ACCESS.pop();
696+
SAFE_STACK_POP;
676697

677698
if (std::type_index(a1.type()) != std::type_index(typeid(void *)))
678699
{
@@ -733,6 +754,7 @@ OMResult<std::any, err::OMValidationError> OMInterpreter::operand_invokeany(std:
733754
}
734755
void OMInterpreter::operand_dup(std::shared_ptr<OMFrameMetadata> frame)
735756
{
757+
STACK_CHECK;
736758
STACK_ACCESS.push(STACK_ACCESS.top());
737759
frame->offset++;
738760
}
@@ -742,18 +764,19 @@ util::OMResult<std::any, err::OMValidationError> OMInterpreter::operand_return(s
742764
}
743765
util::OMResult<std::any, err::OMValidationError> OMInterpreter::popFrame(std::shared_ptr<OMFrameMetadata> frame)
744766
{
767+
STACK_CHECK;
745768
while (std::type_index(STACK_ACCESS.top().type()) != std::type_index(typeid(std::shared_ptr<OMFrameMetadata>)) ||
746769
std::any_cast<std::shared_ptr<OMFrameMetadata>>(STACK_ACCESS.top()) != frame)
747770
{
748-
STACK_ACCESS.pop();
771+
SAFE_STACK_POP;
749772
if (STACK_ACCESS.empty())
750773
{
751774
return util::OMResult<std::any, err::OMValidationError>::err(
752775
{err::Instructions, "whole operator stack is popped! tower is crashing!", fetchCurrentPosition(frame)});
753776
}
754777
}
755778

756-
STACK_ACCESS.pop();
779+
SAFE_STACK_POP;
757780
return util::OMResult<std::any, err::OMValidationError>::ok(nullptr);
758781
}
759782
void OMInterpreter::operand_new(std::shared_ptr<OMFrameMetadata> frame)
@@ -784,7 +807,7 @@ void OMInterpreter::operand_aconst_null(std::shared_ptr<OMFrameMetadata> frame)
784807
}
785808
void OMInterpreter::operand_pop(std::shared_ptr<OMFrameMetadata> frame)
786809
{
787-
STACK_ACCESS.pop();
810+
SAFE_STACK_POP;
788811
frame->offset++;
789812
}
790813
void *OMInterpreter::newString(std::string data)

0 commit comments

Comments
 (0)