Unit 3
What is a secure programming language?
You should read Cifuentes & Bierman (2019) and then answer the questions below, adding them as evidence to your e-portfolio.
- What factors determine whether a programming language is secure or not?
- Could Python be classed as a secure language? Justify your answer.
- Python would be a better language to create operating systems than C. Discuss.
Cifuentes & Bierman (2019) define a secure programming language as one that includes built-in mechanisms for developing secure applications, particularly those that prevent:
- buffer errors,
- injections,
- information leaks.
Notably, none of the programming languages examined in their study meet these criteria. That said, the idea of a “silver bullet” language that prevents all such issues seems, at best, utopian. The wide variety of popular programming languages today reflect their design goals: they aim to solve different problems with different and often conflicting approaches. Moreover, general-purpose languages are meant to be adaptable across domains, so built-in protections against specific threats like XSS or SQL injections would often be impractical.
Still, some widely used languages come close to the definition of secure. For example, high-level languages like Java or Python throw exceptions when trying to access array elements outside their bounds, preventing buffer errors (Python Software Foundation, 2025a; Oracle, no date). Similarly, domain-specific libraries offer tools for safer input handling. Jsoup, for example, sanitizes HTML in Java, and the Exposed library in Kotlin alters how developers work with user input in SQL, reducing the risk of injection vulnerabilities (JetBrains, 2025; Hedley, no date).
Preventing information leaks, however, remains the developer’s responsibility, and rightly so. While a theoretical “secure” language might block unintentional leaks, most applications still need to share data. The key here is controlling access through proper authorization. This is why the focus in computer security should be on promoting safe data handling practices, secure transmission methods, and design patterns that help developers write safe code. This in turn will render any language, including Python, safe.
Lastly, regarding the question of whether Python would be a better language than C for writing operating systems: Python is an interpreted language, executed by a virtual machine. This introduces significant performance overhead. (GeeksforGeeks, 2024; Python Software Foundation, 2025b) While its high-level abstractions make development easier, they depend heavily on the runtime to translate them into low-level machine instructions. This makes Python ill-suited for the low-level, performance-critical demands of an operating system.
References
Cifuentes, C. and Bierman, G. (2019) ‘What is a Secure Programming Language?’, in B.S. Lerner, R. Bodík, and S. Krishnamurthi (eds) 3rd Summit on Advances in Programming Languages (SNAPL 2019). Dagstuhl, Germany: Schloss Dagstuhl – Leibniz-Zentrum für Informatik (Leibniz International Proceedings in Informatics (LIPIcs)), p. 3:1-3:15. Available at: https://doi.org/10.4230/LIPIcs.SNAPL.2019.3.
GeeksforGeeks (2024) Python Virtual Machine, GeeksforGeeks. Available at: https://www.geeksforgeeks.org/python/python-virtual-machine/ (Accessed: 16 July 2025).
Hedley, J. (no date) Prevent cross site scripting with jsoup. Available at: https://jsoup.org/cookbook/cleaning-html/safelist-sanitizer (Accessed: 16 July 2025).
JetBrains (2025) Get started with Exposed, an ORM framework for Kotlin, Exposed Help. Available at: https://www.jetbrains.com/help/docs/1.0.0-beta-3/getting-started-with-exposed.html (Accessed: 16 July 2025).
Oracle (no date) IndexOutOfBoundsException (Java Platform SE 8). Available at: https://docs.oracle.com/javase/8/docs/api/java/lang/IndexOutOfBoundsException.html (Accessed: 16 July 2025).
Python Software Foundation (2025a) Built-in Exceptions, Python documentation. Available at: https://docs.python.org/3/library/exceptions.html (Accessed: 16 July 2025).
Python Software Foundation (2025b) Glossary, Python documentation. Available at: https://docs.python.org/3/glossary.html (Accessed: 16 July 2025).
Coding activity: Exploring Python tools and features
Part 1
In this example, you will compile and run a program in C using the Jupyter notebook workspace provided (Buffer Overflow in C). The program is already provided as bufoverflow.c - a simple program that creates a buffer and then asks you for a name, and prints it back out to the screen.
This is the code in bufoverflow.c. You are able to download the zip file ‘buffer-overflow-in-c’. Additional instructions are provided in the Buffer Overflow PDF.
#include <stdio.h>
int main(int argc, char **argv)
{
char buf[8]; // buffer for eight characters
printf("Enter name: ");
gets(buf); // read from stdio (sensitive function!)
printf("%s\n", buf); // print out data stored in buf
return 0; // 0 as return value
}
Now compile and run the code. To test it, enter your first name (or at least the first 8 characters of it) you should get the output which is just your name repeated back to you.
Run the code a second time (from the command window this can be achieved by entering ./bufoverflow on the command line). This time, enter a string of 10 or more characters.
- What happens?
- What does the output message mean?
To compile the provided C code, gcc
was used, and then the program was executed from the generated file:
gcc bufoverflow.c
./a.out
When run for the first time with valid input (fewer than 8 characters), the program prints the entered data correctly:
Enter name: Sergei
Sergei
When given longer input, an error occurs:
Enter name: 012345678901234567890
012345678901234567890
[1] 22522 abort ./a.out
The program crashes due to a buffer overflow: it tries to write more data than the array can hold. As a result, it attempts to write to memory outside its allocated space and is terminated by the system.
Part 2
Now carry out a comparison of this code with one in Python (Buffer Overflow in Python), following these instructions:
In your workspace, you will be using the file called Overflow.py. You are able to download the zip file 'buffer-overflow-in-python' along with additional instructions in the PDF 'Exploring Python Tools and Features'.
buffer=[None]*10
for i in range (0,11):
buffer[i]=7
print(buffer)
- Run your code using: Python overflow.py (or use the codio rocket icon)
- What is the result?
- Read about Pylint at http://pylint.pycqa.org/en/latest/tutorial.html
- Install pylint using the following commands:
pip install pylint (in the command shell/ interpreter)
- Run pylint on one of your files and evaluate the output:
pylint your_file
- (Make sure you are in the directory where your file is located before running Pylint)
- What is the result? Does this tell you how to fix the error above?
An attempt to run the application fails because the Python runtime throws an IndexError
when it tries to access an out-of-range index in a list:
python3 Overflow.py
Traceback (most recent call last):
File "~/Downloads/buffer-overflow-in-python/Overflow.py", line 3, in <module>
buffer[i]=7
~~~~~~^^^
IndexError: list assignment index out of range
Interestingly, running pylint
on the file doesn’t flag this improper array access:
************* Module Overflow
Overflow.py:4:0: C0303: Trailing whitespace (trailing-whitespace)
Overflow.py:5:0: C0304: Final newline missing (missing-final-newline)
Overflow.py:1:0: C0114: Missing module docstring (missing-module-docstring)
Overflow.py:1:0: C0103: Module name "Overflow" doesn't conform to snake_case naming style (invalid-name)
------------------------------------------------------------------
Your code has been rated at 0.00/10 (previous run: 0.00/10, +0.00)
Activity: The producer-consumer mechanism
Run producer-consumer.py in your chosen Jupyter Notebook workspace (Producer-Consumer Mechanism), where the queue data structure is used.
You can also download the 'producer-consumer-mechanism' zip file.
# code source: https://techmonger.github.io/55/producer-consumer-python/
from threading import Thread
from queue import Queue
q = Queue()
final_results = []
def producer():
for i in range(100):
q.put(i)
def consumer():
while True:
number = q.get()
result = (number, number**2)
final_results.append(result)
q.task_done()
for i in range(5):
t = Thread(target=consumer)
t.daemon = True
t.start()
producer()
q.join()
print (final_results)
Answer the following questions:
- How is the queue data structure used to achieve the purpose of the code?
- What is the purpose of q.put(I)?
- What is achieved by q.get()?
- What functionality is provided by q.join()?
- Extend this producer-consumer code to make the producer-consumer scenario available in a secure way. What technique(s) would be appropriate to apply?
The provided code snippet makes use of the Python’s Queue
class that implements a synchronized queue (Python Software Foundation, 2025). The producer()
function continuously generates numbers that are submitted as tasks to the queue by calling put()
. Consumers are run in background threads and will execute the tasks as follows:
- Consumer will try to get the next task from the queue with
get()
. If there’s no task available, the thread will wait. - The task is processed; the calculated value is added to the
final_results
collection. - After processing is done, the queue is informed of that. In case the queue is blocking some thread with
join()
and all tasks have been processed, the thread will resume.
However, the code snippet in the task only demonstrates the concepts roughly and lacks detail in some areas, which could render a production application unstable or vulnerable. I would adjust the snippet as follows to improve the code quality:
- Limit queue size to prevent excessive resource consumption. This could be useful to prevent denial of service attacks in case the queue was exposed to the Internet via some endpoint.
- Implement thread safety when accessing shared resources (
final_results
) to prevent race conditions. Otherwise different threads may try to access the collection and write data simultaneously, resulting in undefined behavior. - Implement graceful shutdown for the consumer threads. In the initial snippet version, the threads would remain in memory until the script is stopped. In the updated version, a
STOP_SIGNAL
object is used to signal that there will be no further tasks and the loop can be shut down. Then after the queue resumes the main thread, the consumer threads are shut down as well.
from queue import Queue
from threading import Thread, Lock
# Limit maximum queue size to avoid excessive resource consumption
q = Queue(maxsize=25)
# Add lock to implement thread safety when accessing final_results
results_lock = Lock()
final_results = []
# Dedicated object to initiate thread shutdown
STOP_SIGNAL = object()
def producer():
for i in range(100):
q.put(i)
# Send the stop signal to all consumers
for _ in range(5):
q.put(STOP_SIGNAL)
def consumer():
while True:
number = q.get()
# Stop the loop when tasks are done
if number is STOP_SIGNAL:
q.task_done()
break
# Only process valid input
if isinstance(number, int):
result = (number, number ** 2)
with results_lock:
final_results.append(result)
q.task_done()
consumers = []
for i in range(5):
t = Thread(target=consumer)
t.daemon = True
t.start()
consumers.append(t)
producer()
q.join()
for t in consumers:
t.join()
print(final_results)
References
Python Software Foundation (2025) queue — A synchronized queue class, Python documentation. Available at: https://docs.python.org/3/library/queue.html (Accessed: 16 July 2025).